aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/ex_getln.c
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-11-29 22:39:54 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-11-29 22:39:54 +0000
commit21cb7d04c387e4198ca8098a884c78b56ffcf4c2 (patch)
tree84fe5690df1551f0bb2bdfe1a13aacd29ebc1de7 /src/nvim/ex_getln.c
parentd9c904f85a23a496df4eb6be42aa43f007b22d50 (diff)
parent4a8bf24ac690004aedf5540fa440e788459e5e34 (diff)
downloadrneovim-colorcolchar.tar.gz
rneovim-colorcolchar.tar.bz2
rneovim-colorcolchar.zip
Merge remote-tracking branch 'upstream/master' into colorcolcharcolorcolchar
Diffstat (limited to 'src/nvim/ex_getln.c')
-rw-r--r--src/nvim/ex_getln.c616
1 files changed, 288 insertions, 328 deletions
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 76c3680742..64ef17b157 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -1,12 +1,10 @@
-// This is an open source non-commercial project. Dear PVS-Studio, please check
-// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
-
// ex_getln.c: Functions for entering and editing an Ex command line.
#include <assert.h>
#include <inttypes.h>
#include <limits.h>
#include <stdbool.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
@@ -17,7 +15,7 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/vim.h"
#include "nvim/arabic.h"
-#include "nvim/ascii.h"
+#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
#include "nvim/charset.h"
@@ -29,21 +27,23 @@
#include "nvim/edit.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/vars.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
#include "nvim/ex_getln.h"
#include "nvim/extmark.h"
+#include "nvim/func_attr.h"
#include "nvim/garray.h"
#include "nvim/getchar.h"
#include "nvim/gettext.h"
#include "nvim/globals.h"
-#include "nvim/grid.h"
-#include "nvim/highlight_defs.h"
+#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
#include "nvim/keycodes.h"
-#include "nvim/macros.h"
+#include "nvim/macros_defs.h"
+#include "nvim/map_defs.h"
#include "nvim/mapping.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
@@ -55,22 +55,24 @@
#include "nvim/normal.h"
#include "nvim/ops.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
+#include "nvim/option_vars.h"
#include "nvim/optionstr.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
#include "nvim/path.h"
#include "nvim/popupmenu.h"
-#include "nvim/pos.h"
+#include "nvim/pos_defs.h"
#include "nvim/profile.h"
#include "nvim/regexp.h"
-#include "nvim/screen.h"
#include "nvim/search.h"
#include "nvim/state.h"
#include "nvim/strings.h"
+#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/usercmd.h"
-#include "nvim/vim.h"
+#include "nvim/vim_defs.h"
#include "nvim/viml/parser/expressions.h"
#include "nvim/viml/parser/parser.h"
#include "nvim/window.h"
@@ -82,6 +84,7 @@ static unsigned last_prompt_id = 0;
typedef struct {
colnr_T vs_curswant;
colnr_T vs_leftcol;
+ colnr_T vs_skipcol;
linenr_T vs_topline;
int vs_topfill;
linenr_T vs_botline;
@@ -104,7 +107,7 @@ typedef struct {
typedef struct command_line_state {
VimState state;
int firstc;
- long count;
+ int count;
int indent;
int c;
int gotesc; // true when <ESC> just typed
@@ -126,9 +129,34 @@ typedef struct command_line_state {
int ignore_drag_release;
int break_ctrl_c;
expand_T xpc;
- long *b_im_ptr;
+ OptInt *b_im_ptr;
+ buf_T *b_im_ptr_buf; ///< buffer where b_im_ptr is valid
} CommandLineState;
+typedef struct cmdpreview_undo_info {
+ u_header_T *save_b_u_oldhead;
+ u_header_T *save_b_u_newhead;
+ u_header_T *save_b_u_curhead;
+ int save_b_u_numhead;
+ bool save_b_u_synced;
+ int save_b_u_seq_last;
+ int save_b_u_save_nr_last;
+ int save_b_u_seq_cur;
+ time_t save_b_u_time_cur;
+ int save_b_u_save_nr_cur;
+ char *save_b_u_line_ptr;
+ linenr_T save_b_u_line_lnum;
+ colnr_T save_b_u_line_colnr;
+} CpUndoInfo;
+
+typedef struct cmdpreview_buf_info {
+ buf_T *buf;
+ OptInt save_b_p_ul;
+ int save_b_changed;
+ varnumber_T save_changedtick;
+ CpUndoInfo undo_info;
+} CpBufInfo;
+
typedef struct cmdpreview_win_info {
win_T *win;
pos_T save_w_cursor;
@@ -137,17 +165,6 @@ typedef struct cmdpreview_win_info {
int save_w_p_cuc;
} CpWinInfo;
-typedef struct cmdpreview_buf_info {
- buf_T *buf;
- bool save_b_u_synced;
- time_t save_b_u_time_cur;
- long save_b_u_seq_cur;
- u_header_T *save_b_u_newhead;
- long save_b_p_ul;
- int save_b_changed;
- varnumber_T save_changedtick;
-} CpBufInfo;
-
typedef struct cmdpreview_info {
kvec_t(CpWinInfo) win_info;
kvec_t(CpBufInfo) buf_info;
@@ -187,15 +204,14 @@ static int cedit_key = -1; ///< key value of 'cedit' option
#endif
static handle_T cmdpreview_bufnr = 0;
-static long cmdpreview_ns = 0;
-
-static int cmd_hkmap = 0; // Hebrew mapping during command line
+static int cmdpreview_ns = 0;
static void save_viewstate(win_T *wp, viewstate_T *vs)
FUNC_ATTR_NONNULL_ALL
{
vs->vs_curswant = wp->w_curswant;
vs->vs_leftcol = wp->w_leftcol;
+ vs->vs_skipcol = wp->w_skipcol;
vs->vs_topline = wp->w_topline;
vs->vs_topfill = wp->w_topfill;
vs->vs_botline = wp->w_botline;
@@ -207,6 +223,7 @@ static void restore_viewstate(win_T *wp, viewstate_T *vs)
{
wp->w_curswant = vs->vs_curswant;
wp->w_leftcol = vs->vs_leftcol;
+ wp->w_skipcol = vs->vs_skipcol;
wp->w_topline = vs->vs_topline;
wp->w_topfill = vs->vs_topfill;
wp->w_botline = vs->vs_botline;
@@ -232,14 +249,9 @@ static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_s
int *skiplen, int *patlen)
FUNC_ATTR_NONNULL_ALL
{
- char *cmd;
char *p;
bool delim_optional = false;
- int delim;
- char *end;
- char *dummy;
- pos_T save_cursor;
- bool use_last_pat;
+ const char *dummy;
bool retval = false;
magic_T magic = 0;
@@ -273,7 +285,7 @@ static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_s
cmdmod_T dummy_cmdmod;
parse_command_modifiers(&ea, &dummy, &dummy_cmdmod, true);
- cmd = skip_range(ea.cmd, NULL);
+ char *cmd = skip_range(ea.cmd, NULL);
if (vim_strchr("sgvl", (uint8_t)(*cmd)) == NULL) {
goto theend;
}
@@ -298,7 +310,7 @@ static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_s
if (*p == '!') {
p = skipwhite(p + 1);
}
- while (ASCII_ISALPHA(*(p = skipwhite((char *)p)))) {
+ while (ASCII_ISALPHA(*(p = skipwhite(p)))) {
p++;
}
if (*p == NUL) {
@@ -324,11 +336,11 @@ static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_s
}
p = skipwhite(p);
- delim = (delim_optional && vim_isIDc((uint8_t)(*p))) ? ' ' : *p++;
+ int delim = (delim_optional && vim_isIDc((uint8_t)(*p))) ? ' ' : *p++;
*search_delim = delim;
- end = skip_regexp_ex(p, delim, magic_isset(), NULL, NULL, &magic);
+ char *end = skip_regexp_ex(p, delim, magic_isset(), NULL, NULL, &magic);
- use_last_pat = end == p && *end == delim;
+ bool use_last_pat = end == p && *end == delim;
if (end == p && !use_last_pat) {
goto theend;
}
@@ -349,7 +361,7 @@ static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_s
*patlen = (int)(end - p);
// parse the address range
- save_cursor = curwin->w_cursor;
+ pos_T save_cursor = curwin->w_cursor;
curwin->w_cursor = s->search_start;
parse_cmd_address(&ea, &dummy, true);
if (ea.addr_count > 0) {
@@ -375,13 +387,10 @@ theend:
}
// May do 'incsearch' highlighting if desired.
-static void may_do_incsearch_highlighting(int firstc, long count, incsearch_state_T *s)
+static void may_do_incsearch_highlighting(int firstc, int count, incsearch_state_T *s)
{
pos_T end_pos;
- proftime_T tm;
int skiplen, patlen;
- char next_char;
- bool use_last_pat;
int search_delim;
// Parsing range may already set the last search pattern.
@@ -418,9 +427,9 @@ static void may_do_incsearch_highlighting(int firstc, long count, incsearch_stat
int found; // do_search() result
// Use the previous pattern for ":s//".
- next_char = ccline.cmdbuff[skiplen + patlen];
- use_last_pat = patlen == 0 && skiplen > 0
- && ccline.cmdbuff[skiplen - 1] == next_char;
+ char next_char = ccline.cmdbuff[skiplen + patlen];
+ bool use_last_pat = patlen == 0 && skiplen > 0
+ && ccline.cmdbuff[skiplen - 1] == next_char;
// If there is no pattern, don't do anything.
if (patlen == 0 && !use_last_pat) {
@@ -433,7 +442,7 @@ static void may_do_incsearch_highlighting(int firstc, long count, incsearch_stat
ui_flush();
emsg_off++; // So it doesn't beep if bad expr
// Set the time limit to half a second.
- tm = profile_setlimit(500L);
+ proftime_T tm = profile_setlimit(500);
if (!p_hls) {
search_flags += SEARCH_KEEP;
}
@@ -477,7 +486,7 @@ static void may_do_incsearch_highlighting(int firstc, long count, incsearch_stat
// first restore the old curwin values, so the screen is
// positioned in the same way as the actual search command
restore_viewstate(curwin, &s->old_viewstate);
- changed_cline_bef_curs();
+ changed_cline_bef_curs(curwin);
update_topline(curwin);
if (found != 0) {
@@ -506,6 +515,7 @@ static void may_do_incsearch_highlighting(int firstc, long count, incsearch_stat
}
validate_cursor();
+
// May redraw the status line to show the cursor position.
if (p_ru && (curwin->w_status_height > 0 || global_stl_height() > 0)) {
curwin->w_redr_status = true;
@@ -588,7 +598,7 @@ static void finish_incsearch_highlighting(int gotesc, incsearch_state_T *s, bool
curwin->w_cursor = s->save_cursor;
setpcmark();
}
- curwin->w_cursor = s->search_start; // -V519
+ curwin->w_cursor = s->search_start;
}
restore_viewstate(curwin, &s->old_viewstate);
highlight_match = false;
@@ -600,6 +610,7 @@ static void finish_incsearch_highlighting(int gotesc, incsearch_state_T *s, bool
magic_overruled = s->magic_overruled_save;
validate_cursor(); // needed for TAB
+ status_redraw_all();
redraw_all_later(UPD_SOME_VALID);
if (call_update_screen) {
update_screen();
@@ -641,7 +652,7 @@ static void init_ccline(int firstc, int indent)
/// @param count only used for incremental search
/// @param indent indent for inside conditionals
/// @param clear_ccline clear ccline first
-static uint8_t *command_line_enter(int firstc, long count, int indent, bool clear_ccline)
+static uint8_t *command_line_enter(int firstc, int count, int indent, bool clear_ccline)
{
// can be invoked recursively, identify each level
static int cmdline_level = 0;
@@ -680,11 +691,6 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool clea
s->break_ctrl_c = true;
}
- // start without Hebrew mapping for a command line
- if (s->firstc == ':' || s->firstc == '=' || s->firstc == '>') {
- cmd_hkmap = 0;
- }
-
init_ccline(s->firstc, s->indent);
ccline.prompt_id = last_prompt_id++;
ccline.level = cmdline_level;
@@ -698,12 +704,8 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool clea
ExpandInit(&s->xpc);
ccline.xpc = &s->xpc;
- if (curwin->w_p_rl && *curwin->w_p_rlc == 's'
- && (s->firstc == '/' || s->firstc == '?')) {
- cmdmsg_rl = true;
- } else {
- cmdmsg_rl = false;
- }
+ cmdmsg_rl = (curwin->w_p_rl && *curwin->w_p_rlc == 's'
+ && (s->firstc == '/' || s->firstc == '?'));
msg_grid_validate();
@@ -741,7 +743,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool clea
} else {
s->b_im_ptr = &curbuf->b_p_imsearch;
}
-
+ s->b_im_ptr_buf = curbuf;
if (*s->b_im_ptr == B_IMODE_LMAP) {
State |= MODE_LANGMAP;
}
@@ -795,7 +797,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool clea
// Redraw the statusline in case it uses the current mode using the mode()
// function.
- if (!cmd_silent) {
+ if (!cmd_silent && !exmode_active) {
bool found_one = false;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
@@ -844,6 +846,16 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool clea
cmdmsg_rl = false;
+ // We could have reached here without having a chance to clean up wild menu
+ // if certain special keys like <Esc> or <C-\> were used as wildchar. Make
+ // sure to still clean up to avoid memory corruption.
+ if (cmdline_pum_active()) {
+ cmdline_pum_remove();
+ }
+ wildmenu_cleanup(&ccline);
+ s->did_wild_list = false;
+ s->wim_index = 0;
+
ExpandCleanup(&s->xpc);
ccline.xpc = NULL;
@@ -914,6 +926,9 @@ theend:
ui_call_cmdline_hide(ccline.level);
msg_ext_clear_later();
}
+ if (!cmd_silent) {
+ status_redraw_all(); // redraw to show mode change
+ }
cmdline_level--;
@@ -928,6 +943,8 @@ theend:
static int command_line_check(VimState *state)
{
+ CommandLineState *s = (CommandLineState *)state;
+
redir_off = true; // Don't redirect the typed command.
// Repeated, because a ":redir" inside
// completion may switch it on.
@@ -937,6 +954,9 @@ static int command_line_check(VimState *state)
// that occurs while typing a command should
// cause the command not to be executed.
+ // Trigger SafeState if nothing is pending.
+ may_trigger_safestate(s->xpc.xp_numfiles <= 0);
+
cursorcmd(); // set the cursor on the right spot
ui_cursor_shape();
return 1;
@@ -1142,7 +1162,7 @@ static int command_line_execute(VimState *state, int key)
} else if (s->c == K_COMMAND) {
do_cmdline(NULL, getcmdkeycmd, NULL, DOCMD_NOWAIT);
} else {
- map_execute_lua();
+ map_execute_lua(false);
}
// nvim_select_popupmenu_item() can be called from the handling of
@@ -1166,9 +1186,6 @@ static int command_line_execute(VimState *state, int key)
if (KeyTyped) {
s->some_key_typed = true;
- if (cmd_hkmap) {
- s->c = hkmap(s->c);
- }
if (cmdmsg_rl && !KeyStuffed) {
// Invert horizontal movements and operations. Only when
@@ -1225,13 +1242,14 @@ static int command_line_execute(VimState *state, int key)
s->c = wildmenu_translate_key(&ccline, s->c, &s->xpc, s->did_wild_list);
}
- if (cmdline_pum_active() || s->did_wild_list) {
+ int wild_type = 0;
+ const bool key_is_wc = (s->c == p_wc && KeyTyped) || s->c == p_wcm;
+ if ((cmdline_pum_active() || s->did_wild_list) && !key_is_wc) {
// Ctrl-Y: Accept the current selection and close the popup menu.
// Ctrl-E: cancel the cmdline popup menu and return the original text.
if (s->c == Ctrl_E || s->c == Ctrl_Y) {
- const int wild_type = (s->c == Ctrl_E) ? WILD_CANCEL : WILD_APPLY;
+ wild_type = (s->c == Ctrl_E) ? WILD_CANCEL : WILD_APPLY;
(void)nextwild(&s->xpc, wild_type, WILD_NO_BEEP, s->firstc != '@');
- s->c = Ctrl_E;
}
}
@@ -1240,7 +1258,7 @@ static int command_line_execute(VimState *state, int key)
// 'wildcharm' or Ctrl-N or Ctrl-P or Ctrl-A or Ctrl-L).
// If the popup menu is displayed, then PageDown and PageUp keys are
// also used to navigate the menu.
- bool end_wildmenu = (!(s->c == p_wc && KeyTyped) && s->c != p_wcm && s->c != Ctrl_Z
+ bool end_wildmenu = (!key_is_wc && s->c != Ctrl_Z
&& s->c != Ctrl_N && s->c != Ctrl_P && s->c != Ctrl_A
&& s->c != Ctrl_L);
end_wildmenu = end_wildmenu && (!cmdline_pum_active()
@@ -1307,7 +1325,7 @@ static int command_line_execute(VimState *state, int key)
if (!cmd_silent) {
if (!ui_has(kUICmdline)) {
- cmd_cursor_goto(msg_row, 0);
+ msg_cursor_goto(msg_row, 0);
}
ui_flush();
}
@@ -1344,13 +1362,19 @@ static int command_line_execute(VimState *state, int key)
}
s->do_abbr = true; // default: check for abbreviation
+
+ // If already used to cancel/accept wildmenu, don't process the key further.
+ if (wild_type == WILD_CANCEL || wild_type == WILD_APPLY) {
+ return command_line_not_changed(s);
+ }
+
return command_line_handle_key(s);
}
// May adjust 'incsearch' highlighting for typing CTRL-G and CTRL-T, go to next
// or previous match.
// Returns FAIL when calling command_line_not_changed.
-static int may_do_command_line_next_incsearch(int firstc, long count, incsearch_state_T *s,
+static int may_do_command_line_next_incsearch(int firstc, int count, incsearch_state_T *s,
bool next_match)
FUNC_ATTR_NONNULL_ALL
{
@@ -1376,7 +1400,6 @@ static int may_do_command_line_next_incsearch(int firstc, long count, incsearch_
pos_T t;
char *pat;
int search_flags = SEARCH_NOOF;
- char save;
if (search_delim == ccline.cmdbuff[skiplen]) {
pat = last_search_pattern();
@@ -1405,7 +1428,7 @@ static int may_do_command_line_next_incsearch(int firstc, long count, incsearch_
search_flags += SEARCH_KEEP;
}
emsg_off++;
- save = pat[patlen];
+ char save = pat[patlen];
pat[patlen] = NUL;
int found = searchit(curwin, curbuf, &t, NULL,
next_match ? FORWARD : BACKWARD,
@@ -1443,7 +1466,7 @@ static int may_do_command_line_next_incsearch(int firstc, long count, incsearch_
set_search_match(&s->match_end);
curwin->w_cursor = s->match_start;
- changed_cline_bef_curs();
+ changed_cline_bef_curs(curwin);
update_topline(curwin);
validate_cursor();
highlight_match = true;
@@ -1479,10 +1502,8 @@ static int command_line_erase_chars(CommandLineState *s)
}
if (ccline.cmdpos > 0) {
- char *p;
-
int j = ccline.cmdpos;
- p = mb_prevptr(ccline.cmdbuff, ccline.cmdbuff + j);
+ char *p = mb_prevptr(ccline.cmdbuff, ccline.cmdbuff + j);
if (s->c == Ctrl_W) {
while (p > ccline.cmdbuff && ascii_isspace(*p)) {
@@ -1525,11 +1546,7 @@ static int command_line_erase_chars(CommandLineState *s)
XFREE_CLEAR(ccline.cmdbuff); // no commandline to return
if (!cmd_silent && !ui_has(kUICmdline)) {
- if (cmdmsg_rl) {
- msg_col = Columns;
- } else {
- msg_col = 0;
- }
+ msg_col = 0;
msg_putchar(' '); // delete ':'
}
s->is_state.search_start = s->is_state.save_cursor;
@@ -1543,20 +1560,21 @@ static int command_line_erase_chars(CommandLineState *s)
/// language :lmap mappings and/or Input Method.
static void command_line_toggle_langmap(CommandLineState *s)
{
+ OptInt *b_im_ptr = buf_valid(s->b_im_ptr_buf) ? s->b_im_ptr : NULL;
if (map_to_exists_mode("", MODE_LANGMAP, false)) {
// ":lmap" mappings exists, toggle use of mappings.
State ^= MODE_LANGMAP;
- if (s->b_im_ptr != NULL) {
+ if (b_im_ptr != NULL) {
if (State & MODE_LANGMAP) {
- *s->b_im_ptr = B_IMODE_LMAP;
+ *b_im_ptr = B_IMODE_LMAP;
} else {
- *s->b_im_ptr = B_IMODE_NONE;
+ *b_im_ptr = B_IMODE_NONE;
}
}
}
- if (s->b_im_ptr != NULL) {
- if (s->b_im_ptr == &curbuf->b_p_iminsert) {
+ if (b_im_ptr != NULL) {
+ if (b_im_ptr == &curbuf->b_p_iminsert) {
set_iminsert_global(curbuf);
} else {
set_imsearch_global(curbuf);
@@ -1598,8 +1616,10 @@ static int command_line_insert_reg(CommandLineState *s)
}
}
+ bool literally = false;
if (s->c != ESC) { // use ESC to cancel inserting register
- cmdline_paste(s->c, i == Ctrl_R, false);
+ literally = i == Ctrl_R || is_literal_register(s->c);
+ cmdline_paste(s->c, literally, false);
// When there was a serious error abort getting the
// command line.
@@ -1624,8 +1644,9 @@ static int command_line_insert_reg(CommandLineState *s)
ccline.special_char = NUL;
redrawcmd();
- // The text has been stuffed, the command line didn't change yet.
- return CMDLINE_NOT_CHANGED;
+ // With "literally": the command line has already changed.
+ // Else: the text has been stuffed, but the command line didn't change yet.
+ return literally ? CMDLINE_CHANGED : CMDLINE_NOT_CHANGED;
}
/// Handle the Left and Right mouse clicks in the command-line mode.
@@ -1656,7 +1677,7 @@ 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);
- for (;;) {
+ while (true) {
// one step backwards
if (!next_match) {
if (s->hiscnt == get_hislen()) {
@@ -1729,7 +1750,6 @@ static int command_line_browse_history(CommandLineState *s)
if (s->hiscnt != s->save_hiscnt) {
// jumped to other entry
char *p;
- int len = 0;
int old_firstc;
XFREE_CLEAR(ccline.cmdbuff);
@@ -1743,6 +1763,7 @@ static int command_line_browse_history(CommandLineState *s)
if (s->histype == HIST_SEARCH
&& p != s->lookfor
&& (old_firstc = (uint8_t)p[strlen(p) + 1]) != s->firstc) {
+ int len = 0;
// Correct for the separator character used when
// adding the history entry vs the one used now.
// First loop: count length.
@@ -1814,8 +1835,10 @@ static int command_line_handle_key(CommandLineState *s)
case K_INS:
case K_KINS:
ccline.overstrike = !ccline.overstrike;
-
ui_cursor_shape(); // may show different cursor shape
+ may_trigger_modechanged();
+ status_redraw_curbuf();
+ redraw_statuslines();
return command_line_not_changed(s);
case Ctrl_HAT:
@@ -1857,12 +1880,12 @@ static int command_line_handle_key(CommandLineState *s)
case Ctrl_R: // insert register
switch (command_line_insert_reg(s)) {
- case CMDLINE_NOT_CHANGED:
- return command_line_not_changed(s);
case GOTO_NORMAL_MODE:
return 0; // back to cmd mode
- default:
+ case CMDLINE_CHANGED:
return command_line_changed(s);
+ default:
+ return command_line_not_changed(s);
}
case Ctrl_D:
@@ -2015,7 +2038,7 @@ static int command_line_handle_key(CommandLineState *s)
if (nextwild(&s->xpc, wild_type, 0, s->firstc != '@') == FAIL) {
break;
}
- return command_line_not_changed(s);
+ return command_line_changed(s);
}
FALLTHROUGH;
@@ -2037,7 +2060,7 @@ static int command_line_handle_key(CommandLineState *s)
if (nextwild(&s->xpc, wild_type, 0, s->firstc != '@') == FAIL) {
break;
}
- return command_line_not_changed(s);
+ return command_line_changed(s);
} else {
switch (command_line_browse_history(s)) {
case CMDLINE_CHANGED:
@@ -2098,7 +2121,6 @@ static int command_line_handle_key(CommandLineState *s)
if (!p_ari) {
break;
}
- cmd_hkmap = !cmd_hkmap;
return command_line_not_changed(s);
default:
@@ -2123,7 +2145,7 @@ static int command_line_handle_key(CommandLineState *s)
// put the character in the command line
if (IS_SPECIAL(s->c) || mod_mask != 0) {
- put_on_cmdline((char *)get_special_key_name(s->c, mod_mask), -1, true);
+ put_on_cmdline(get_special_key_name(s->c, mod_mask), -1, true);
} else {
int j = utf_char2bytes(s->c, IObuff);
IObuff[j] = NUL; // exclude composing chars
@@ -2183,7 +2205,7 @@ handle_T cmdpreview_get_bufnr(void)
return cmdpreview_bufnr;
}
-long cmdpreview_get_ns(void)
+int cmdpreview_get_ns(void)
{
return cmdpreview_ns;
}
@@ -2278,9 +2300,51 @@ static void cmdpreview_close_win(void)
}
}
+/// Save the undo state of a buffer for command preview.
+static void cmdpreview_save_undo(CpUndoInfo *cp_undoinfo, buf_T *buf)
+ FUNC_ATTR_NONNULL_ALL
+{
+ cp_undoinfo->save_b_u_synced = buf->b_u_synced;
+ cp_undoinfo->save_b_u_oldhead = buf->b_u_oldhead;
+ cp_undoinfo->save_b_u_newhead = buf->b_u_newhead;
+ cp_undoinfo->save_b_u_curhead = buf->b_u_curhead;
+ cp_undoinfo->save_b_u_numhead = buf->b_u_numhead;
+ cp_undoinfo->save_b_u_seq_last = buf->b_u_seq_last;
+ cp_undoinfo->save_b_u_save_nr_last = buf->b_u_save_nr_last;
+ cp_undoinfo->save_b_u_seq_cur = buf->b_u_seq_cur;
+ cp_undoinfo->save_b_u_time_cur = buf->b_u_time_cur;
+ cp_undoinfo->save_b_u_save_nr_cur = buf->b_u_save_nr_cur;
+ cp_undoinfo->save_b_u_line_ptr = buf->b_u_line_ptr;
+ cp_undoinfo->save_b_u_line_lnum = buf->b_u_line_lnum;
+ cp_undoinfo->save_b_u_line_colnr = buf->b_u_line_colnr;
+}
+
+/// Restore the undo state of a buffer for command preview.
+static void cmdpreview_restore_undo(const CpUndoInfo *cp_undoinfo, buf_T *buf)
+{
+ buf->b_u_oldhead = cp_undoinfo->save_b_u_oldhead;
+ buf->b_u_newhead = cp_undoinfo->save_b_u_newhead;
+ buf->b_u_curhead = cp_undoinfo->save_b_u_curhead;
+ buf->b_u_numhead = cp_undoinfo->save_b_u_numhead;
+ buf->b_u_seq_last = cp_undoinfo->save_b_u_seq_last;
+ buf->b_u_save_nr_last = cp_undoinfo->save_b_u_save_nr_last;
+ buf->b_u_seq_cur = cp_undoinfo->save_b_u_seq_cur;
+ buf->b_u_time_cur = cp_undoinfo->save_b_u_time_cur;
+ buf->b_u_save_nr_cur = cp_undoinfo->save_b_u_save_nr_cur;
+ buf->b_u_line_ptr = cp_undoinfo->save_b_u_line_ptr;
+ buf->b_u_line_lnum = cp_undoinfo->save_b_u_line_lnum;
+ buf->b_u_line_colnr = cp_undoinfo->save_b_u_line_colnr;
+ if (buf->b_u_curhead == NULL) {
+ buf->b_u_synced = cp_undoinfo->save_b_u_synced;
+ }
+}
+
/// Save current state and prepare windows and buffers for command preview.
static void cmdpreview_prepare(CpInfo *cpinfo)
+ FUNC_ATTR_NONNULL_ALL
{
+ Set(ptr_t) saved_bufs = SET_INIT;
+
kv_init(cpinfo->buf_info);
kv_init(cpinfo->win_info);
@@ -2292,20 +2356,19 @@ static void cmdpreview_prepare(CpInfo *cpinfo)
continue;
}
- CpBufInfo cp_bufinfo;
- cp_bufinfo.buf = buf;
+ if (!set_has(ptr_t, &saved_bufs, buf)) {
+ CpBufInfo cp_bufinfo;
+ cp_bufinfo.buf = buf;
+ cp_bufinfo.save_b_p_ul = buf->b_p_ul;
+ cp_bufinfo.save_b_changed = buf->b_changed;
+ cp_bufinfo.save_changedtick = buf_get_changedtick(buf);
+ cmdpreview_save_undo(&cp_bufinfo.undo_info, buf);
+ kv_push(cpinfo->buf_info, cp_bufinfo);
+ set_put(ptr_t, &saved_bufs, buf);
- cp_bufinfo.save_b_u_synced = buf->b_u_synced;
- cp_bufinfo.save_b_u_time_cur = buf->b_u_time_cur;
- cp_bufinfo.save_b_u_seq_cur = buf->b_u_seq_cur;
- cp_bufinfo.save_b_u_newhead = buf->b_u_newhead;
- cp_bufinfo.save_b_p_ul = buf->b_p_ul;
- cp_bufinfo.save_b_changed = buf->b_changed;
- cp_bufinfo.save_changedtick = buf_get_changedtick(buf);
-
- kv_push(cpinfo->buf_info, cp_bufinfo);
-
- buf->b_p_ul = LONG_MAX; // Make sure we can undo all changes
+ u_clearall(buf);
+ buf->b_p_ul = INT_MAX; // Make sure we can undo all changes
+ }
CpWinInfo cp_wininfo;
cp_wininfo.win = win;
@@ -2324,6 +2387,8 @@ static void cmdpreview_prepare(CpInfo *cpinfo)
win->w_p_cuc = false; // Disable 'cursorcolumn' so it doesn't mess up the highlights
}
+ set_destroy(ptr_t, &saved_bufs);
+
cpinfo->save_hls = p_hls;
cpinfo->save_cmdmod = cmdmod;
win_size_save(&cpinfo->save_view);
@@ -2337,8 +2402,9 @@ static void cmdpreview_prepare(CpInfo *cpinfo)
u_sync(true);
}
-// Restore the state of buffers and windows before command preview.
+/// Restore the state of buffers and windows for command preview.
static void cmdpreview_restore_state(CpInfo *cpinfo)
+ FUNC_ATTR_NONNULL_ALL
{
for (size_t i = 0; i < cpinfo->buf_info.size; i++) {
CpBufInfo cp_bufinfo = cpinfo->buf_info.items[i];
@@ -2346,41 +2412,40 @@ static void cmdpreview_restore_state(CpInfo *cpinfo)
buf->b_changed = cp_bufinfo.save_b_changed;
- if (buf->b_u_seq_cur != cp_bufinfo.save_b_u_seq_cur) {
+ // Clear preview highlights.
+ extmark_clear(buf, (uint32_t)cmdpreview_ns, 0, 0, MAXLNUM, MAXCOL);
+
+ if (buf->b_u_seq_cur != cp_bufinfo.undo_info.save_b_u_seq_cur) {
int count = 0;
// Calculate how many undo steps are necessary to restore earlier state.
for (u_header_T *uhp = buf->b_u_curhead ? buf->b_u_curhead : buf->b_u_newhead;
- uhp != NULL && uhp->uh_seq > cp_bufinfo.save_b_u_seq_cur;
+ uhp != NULL;
uhp = uhp->uh_next.ptr, ++count) {}
aco_save_T aco;
aucmd_prepbuf(&aco, buf);
+ // Ensure all the entries will be undone
+ if (curbuf->b_u_synced == false) {
+ u_sync(true);
+ }
// Undo invisibly. This also moves the cursor!
if (!u_undo_and_forget(count, false)) {
abort();
}
aucmd_restbuf(&aco);
-
- // Restore newhead. It is meaningless when curhead is valid, but we must
- // restore it so that undotree() is identical before/after the preview.
- buf->b_u_newhead = cp_bufinfo.save_b_u_newhead;
- buf->b_u_time_cur = cp_bufinfo.save_b_u_time_cur;
}
- if (buf->b_u_curhead == NULL) {
- buf->b_u_synced = cp_bufinfo.save_b_u_synced;
- }
+ u_blockfree(buf);
+ cmdpreview_restore_undo(&cp_bufinfo.undo_info, buf);
if (cp_bufinfo.save_changedtick != buf_get_changedtick(buf)) {
buf_set_changedtick(buf, cp_bufinfo.save_changedtick);
}
buf->b_p_ul = cp_bufinfo.save_b_p_ul; // Restore 'undolevels'
-
- // Clear preview highlights.
- extmark_clear(buf, (uint32_t)cmdpreview_ns, 0, 0, MAXLNUM, MAXCOL);
}
+
for (size_t i = 0; i < cpinfo->win_info.size; i++) {
CpWinInfo cp_wininfo = cpinfo->win_info.items[i];
win_T *win = cp_wininfo.win;
@@ -2429,7 +2494,7 @@ static bool cmdpreview_may_show(CommandLineState *s)
// Copy the command line so we can modify it.
int cmdpreview_type = 0;
char *cmdline = xstrdup(ccline.cmdbuff);
- char *errormsg = NULL;
+ const char *errormsg = NULL;
emsg_off++; // Block errors when parsing the command line, and don't update v:errmsg
if (!parse_cmdline(cmdline, &ea, &cmdinfo, &errormsg)) {
emsg_off--;
@@ -2452,8 +2517,8 @@ static bool cmdpreview_may_show(CommandLineState *s)
CpInfo cpinfo;
bool icm_split = *p_icm == 's'; // inccommand=split
- buf_T *cmdpreview_buf;
- win_T *cmdpreview_win;
+ buf_T *cmdpreview_buf = NULL;
+ win_T *cmdpreview_win = NULL;
emsg_silent++; // Block error reporting as the command may be incomplete,
// but still update v:errmsg
@@ -2579,7 +2644,7 @@ static int command_line_changed(CommandLineState *s)
}
}
- if (cmdmsg_rl || (p_arshape && !p_tbidi)) {
+ if (p_arshape && !p_tbidi) {
// Always redraw the whole command line to fix shaping and
// right-left typing. Not efficient, but it works.
// Do it only when there are no characters left to read
@@ -2601,7 +2666,7 @@ static void abandon_cmdline(void)
if (msg_scrolled == 0) {
compute_cmdrow();
}
- msg("");
+ msg("", 0);
redraw_cmdline = true;
}
@@ -2625,7 +2690,7 @@ static void abandon_cmdline(void)
///
/// @param count only used for incremental search
/// @param indent indent for inside conditionals
-char *getcmdline(int firstc, long count, int indent, bool do_concat FUNC_ATTR_UNUSED)
+char *getcmdline(int firstc, int count, int indent, bool do_concat FUNC_ATTR_UNUSED)
{
return (char *)command_line_enter(firstc, count, indent, true);
}
@@ -2670,7 +2735,7 @@ char *getcmdline_prompt(const int firstc, const char *const prompt, const int at
int msg_silent_saved = msg_silent;
msg_silent = 0;
- char *const ret = (char *)command_line_enter(firstc, 1L, 0, false);
+ char *const ret = (char *)command_line_enter(firstc, 1, 0, false);
if (did_save_ccline) {
restore_cmdline(&save_ccline);
@@ -2690,7 +2755,7 @@ char *getcmdline_prompt(const int firstc, const char *const prompt, const int at
/// Read the 'wildmode' option, fill wim_flags[].
int check_opt_wim(void)
{
- char_u new_wim_flags[4];
+ uint8_t new_wim_flags[4];
int i;
int idx = 0;
@@ -2699,6 +2764,7 @@ int check_opt_wim(void)
}
for (char *p = p_wim; *p; p++) {
+ // Note: Keep this in sync with p_wim_values.
for (i = 0; ASCII_ISALPHA(p[i]); i++) {}
if (p[i] != NUL && p[i] != ',' && p[i] != ':') {
return FAIL;
@@ -2746,6 +2812,9 @@ bool text_locked(void)
if (cmdwin_type != 0) {
return true;
}
+ if (expr_map_locked()) {
+ return true;
+ }
return textlock != 0;
}
@@ -2756,7 +2825,7 @@ void text_locked_msg(void)
emsg(_(get_text_locked_msg()));
}
-char *get_text_locked_msg(void)
+const char *get_text_locked_msg(void)
{
if (cmdwin_type != 0) {
return e_cmdwin;
@@ -2866,7 +2935,7 @@ char *getexline(int c, void *cookie, int indent, bool do_concat)
(void)vgetc();
}
- return getcmdline(c, 1L, indent, do_concat);
+ return getcmdline(c, 1, indent, do_concat);
}
bool cmdline_overstrike(void)
@@ -2926,16 +2995,6 @@ void realloc_cmdbuff(int len)
}
}
-static char *arshape_buf = NULL;
-
-#if defined(EXITFREE)
-void free_arshape_buf(void)
-{
- xfree(arshape_buf);
-}
-
-#endif
-
enum { MAX_CB_ERRORS = 1, };
/// Color expression cmdline using built-in expressions parser
@@ -2950,7 +3009,7 @@ static void color_expr_cmdline(const CmdlineInfo *const colored_ccline,
{
ParserLine parser_lines[] = {
{
- .data = (const char *)colored_ccline->cmdbuff,
+ .data = colored_ccline->cmdbuff,
.size = strlen(colored_ccline->cmdbuff),
.allocated = false,
},
@@ -3054,7 +3113,7 @@ static bool color_cmdline(CmdlineInfo *colored_ccline)
bool can_free_cb = false;
TryState tstate;
Error err = ERROR_INIT;
- const char *err_errmsg = (const char *)e_intern2;
+ const char *err_errmsg = e_intern2;
bool dgc_ret = true;
bool tl_ret = true;
@@ -3087,8 +3146,7 @@ static bool color_cmdline(CmdlineInfo *colored_ccline)
}
if (colored_ccline->cmdbuff[colored_ccline->cmdlen] != NUL) {
arg_allocated = true;
- arg.vval.v_string = xmemdupz((const char *)colored_ccline->cmdbuff,
- (size_t)colored_ccline->cmdlen);
+ arg.vval.v_string = xmemdupz(colored_ccline->cmdbuff, (size_t)colored_ccline->cmdlen);
}
// msg_start() called by e.g. :echo may shift command-line to the first column
// even though msg_silent is here. Two ways to workaround this problem without
@@ -3207,8 +3265,7 @@ color_cmdline_end:
if (arg_allocated) {
ccline_colors->cmdbuff = arg.vval.v_string;
} else {
- ccline_colors->cmdbuff = xmemdupz((const char *)colored_ccline->cmdbuff,
- (size_t)colored_ccline->cmdlen);
+ ccline_colors->cmdbuff = xmemdupz(colored_ccline->cmdbuff, (size_t)colored_ccline->cmdlen);
}
tv_clear(&tv);
return ret;
@@ -3247,98 +3304,7 @@ static void draw_cmdline(int start, int len)
msg_putchar('*');
i += utfc_ptr2len(ccline.cmdbuff + start + i) - 1;
}
- } else if (p_arshape && !p_tbidi && len > 0) {
- bool do_arabicshape = false;
- int mb_l;
- for (int i = start; i < start + len; i += mb_l) {
- char *p = ccline.cmdbuff + i;
- int u8cc[MAX_MCO];
- int u8c = utfc_ptr2char_len(p, u8cc, start + len - i);
- mb_l = utfc_ptr2len_len(p, start + len - i);
- if (ARABIC_CHAR(u8c)) {
- do_arabicshape = true;
- break;
- }
- }
- if (!do_arabicshape) {
- goto draw_cmdline_no_arabicshape;
- }
-
- static size_t buflen = 0;
- assert(len >= 0);
-
- // Do arabic shaping into a temporary buffer. This is very
- // inefficient!
- 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 = (size_t)len * 2 + 2;
- arshape_buf = xmalloc(buflen);
- }
-
- int newlen = 0;
- if (utf_iscomposing(utf_ptr2char(ccline.cmdbuff + start))) {
- // Prepend a space to draw the leading composing char on.
- arshape_buf[0] = ' ';
- newlen = 1;
- }
-
- int prev_c = 0;
- int prev_c1 = 0;
- for (int i = start; i < start + len; i += mb_l) {
- char *p = ccline.cmdbuff + i;
- int u8cc[MAX_MCO];
- int u8c = utfc_ptr2char_len(p, u8cc, start + len - i);
- mb_l = utfc_ptr2len_len(p, start + len - i);
- if (ARABIC_CHAR(u8c)) {
- int pc;
- int pc1 = 0;
- int nc = 0;
- // Do Arabic shaping.
- if (cmdmsg_rl) {
- // Displaying from right to left.
- pc = prev_c;
- pc1 = prev_c1;
- prev_c1 = u8cc[0];
- if (i + mb_l >= start + len) {
- nc = NUL;
- } else {
- nc = utf_ptr2char(p + mb_l);
- }
- } else {
- // Displaying from left to right.
- if (i + mb_l >= start + len) {
- pc = NUL;
- } else {
- int pcc[MAX_MCO];
-
- pc = utfc_ptr2char_len(p + mb_l, pcc, start + len - i - mb_l);
- pc1 = pcc[0];
- }
- nc = prev_c;
- }
- prev_c = u8c;
-
- u8c = arabic_shape(u8c, NULL, &u8cc[0], pc, pc1, nc);
-
- newlen += utf_char2bytes(u8c, arshape_buf + newlen);
- if (u8cc[0] != 0) {
- newlen += utf_char2bytes(u8cc[0], arshape_buf + newlen);
- if (u8cc[1] != 0) {
- newlen += utf_char2bytes(u8cc[1], arshape_buf + newlen);
- }
- }
- } else {
- prev_c = u8c;
- memmove(arshape_buf + newlen, p, (size_t)mb_l);
- newlen += mb_l;
- }
- }
-
- msg_outtrans_len(arshape_buf, newlen);
} else {
-draw_cmdline_no_arabicshape:
if (kv_size(ccline.last_colors.colors)) {
for (size_t i = 0; i < kv_size(ccline.last_colors.colors); i++) {
CmdlineColorChunk chunk = kv_A(ccline.last_colors.colors, i);
@@ -3346,12 +3312,10 @@ draw_cmdline_no_arabicshape:
continue;
}
const int chunk_start = MAX(chunk.start, start);
- msg_outtrans_len_attr(ccline.cmdbuff + chunk_start,
- chunk.end - chunk_start,
- chunk.attr);
+ msg_outtrans_len(ccline.cmdbuff + chunk_start, chunk.end - chunk_start, chunk.attr);
}
} else {
- msg_outtrans_len(ccline.cmdbuff + start, len);
+ msg_outtrans_len(ccline.cmdbuff + start, len, 0);
}
}
}
@@ -3380,14 +3344,14 @@ static void ui_ext_cmdline_show(CmdlineInfo *line)
ADD_C(item, INTEGER_OBJ(chunk.attr));
assert(chunk.end >= chunk.start);
- ADD_C(item, STRING_OBJ(cbuf_as_string((char *)line->cmdbuff + chunk.start,
+ ADD_C(item, STRING_OBJ(cbuf_as_string(line->cmdbuff + chunk.start,
(size_t)(chunk.end - chunk.start))));
ADD_C(content, ARRAY_OBJ(item));
}
} else {
Array item = arena_array(&arena, 2);
ADD_C(item, INTEGER_OBJ(0));
- ADD_C(item, STRING_OBJ(cstr_as_string((char *)(line->cmdbuff))));
+ ADD_C(item, CSTR_AS_OBJ(line->cmdbuff));
content = arena_array(&arena, 1);
ADD_C(content, ARRAY_OBJ(item));
}
@@ -3410,11 +3374,11 @@ void ui_ext_cmdline_block_append(size_t indent, const char *line)
{
char *buf = xmallocz(indent + strlen(line));
memset(buf, ' ', indent);
- memcpy(buf + indent, line, strlen(line)); // -V575
+ memcpy(buf + indent, line, strlen(line));
Array item = ARRAY_DICT_INIT;
ADD(item, INTEGER_OBJ(0));
- ADD(item, STRING_OBJ(cstr_as_string(buf)));
+ ADD(item, CSTR_AS_OBJ(buf));
Array content = ARRAY_DICT_INIT;
ADD(content, ARRAY_OBJ(item));
ADD(cmdline_block, ARRAY_OBJ(content));
@@ -3530,7 +3494,7 @@ void unputcmdline(void)
// part will be redrawn, otherwise it will not. If this function is called
// twice in a row, then 'redraw' should be false and redrawcmd() should be
// called afterwards.
-void put_on_cmdline(char *str, int len, int redraw)
+void put_on_cmdline(const char *str, int len, int redraw)
{
int i;
int m;
@@ -3676,7 +3640,6 @@ static void restore_cmdline(CmdlineInfo *ccp)
static bool cmdline_paste(int regname, bool literally, bool remcr)
{
char *arg;
- char *p;
bool allocated;
// check for valid regname; also accept special characters for CTRL-R in
@@ -3708,7 +3671,7 @@ static bool cmdline_paste(int regname, bool literally, bool remcr)
// When 'incsearch' is set and CTRL-R CTRL-W used: skip the duplicate
// part of the word.
- p = arg;
+ char *p = arg;
if (p_is && regname == Ctrl_W) {
char *w;
int len;
@@ -3741,19 +3704,17 @@ static bool cmdline_paste(int regname, bool literally, bool remcr)
// When "literally" is true, insert literally.
// When "literally" is false, insert as typed, but don't leave the command
// line.
-void cmdline_paste_str(char *s, int literally)
+void cmdline_paste_str(const char *s, int literally)
{
- int c, cv;
-
if (literally) {
put_on_cmdline(s, -1, true);
} else {
while (*s != NUL) {
- cv = (uint8_t)(*s);
+ int cv = (uint8_t)(*s);
if (cv == Ctrl_V && s[1]) {
s++;
}
- c = mb_cptr2char_adv((const char **)&s);
+ int c = mb_cptr2char_adv(&s);
if (cv == Ctrl_V || c == ESC || c == Ctrl_C
|| c == CAR || c == NL || c == Ctrl_L
|| (c == Ctrl_BSL && *s == Ctrl_N)) {
@@ -3781,8 +3742,6 @@ void redrawcmdline(void)
static void redrawcmdprompt(void)
{
- int i;
-
if (cmd_silent) {
return;
}
@@ -3801,7 +3760,7 @@ static void redrawcmdprompt(void)
ccline.cmdindent--;
}
} else {
- for (i = ccline.cmdindent; i > 0; i--) {
+ for (int i = ccline.cmdindent; i > 0; i--) {
msg_putchar(' ');
}
}
@@ -3821,7 +3780,7 @@ void redrawcmd(void)
// when 'incsearch' is set there may be no command line while redrawing
if (ccline.cmdbuff == NULL) {
- cmd_cursor_goto(cmdline_row, 0);
+ msg_cursor_goto(cmdline_row, 0);
msg_clr_eos();
return;
}
@@ -3884,28 +3843,13 @@ void cursorcmd(void)
return;
}
- if (cmdmsg_rl) {
- 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 / Columns);
- msg_col = ccline.cmdspos % Columns;
- if (msg_row >= Rows) {
- msg_row = Rows - 1;
- }
+ msg_row = cmdline_row + (ccline.cmdspos / Columns);
+ msg_col = ccline.cmdspos % Columns;
+ if (msg_row >= Rows) {
+ msg_row = Rows - 1;
}
- cmd_cursor_goto(msg_row, msg_col);
-}
-
-static void cmd_cursor_goto(int row, int col)
-{
- ScreenGrid *grid = &msg_grid_adj;
- grid_adjust(&grid, &row, &col);
- ui_grid_cursor_goto(grid->handle, row, col);
+ msg_cursor_goto(msg_row, msg_col);
}
void gotocmdline(bool clr)
@@ -3914,15 +3858,11 @@ void gotocmdline(bool clr)
return;
}
msg_start();
- if (cmdmsg_rl) {
- msg_col = Columns - 1;
- } else {
- msg_col = 0; // always start in column 0
- }
+ msg_col = 0; // always start in column 0
if (clr) { // clear the bottom line(s)
msg_clr_eos(); // will reset clear_cmdline
}
- cmd_cursor_goto(cmdline_row, 0);
+ msg_cursor_goto(cmdline_row, 0);
}
// Check the word in front of the cursor for an abbreviation.
@@ -4022,11 +3962,9 @@ void escape_fname(char **pp)
/// If 'orig_pat' starts with "~/", replace the home directory with "~".
void tilde_replace(char *orig_pat, int num_files, char **files)
{
- char *p;
-
if (orig_pat[0] == '~' && vim_ispathsep(orig_pat[1])) {
for (int i = 0; i < num_files; i++) {
- p = home_replace_save(NULL, files[i]);
+ char *p = home_replace_save(NULL, files[i]);
xfree(files[i]);
files[i] = p;
}
@@ -4106,12 +4044,24 @@ static char *get_cmdline_completion(void)
}
set_expand_context(p->xpc);
+ if (p->xpc->xp_context == EXPAND_UNSUCCESSFUL) {
+ return NULL;
+ }
+
char *cmd_compl = get_user_cmd_complete(p->xpc, p->xpc->xp_context);
- if (cmd_compl != NULL) {
- return xstrdup(cmd_compl);
+ if (cmd_compl == NULL) {
+ return NULL;
}
- return NULL;
+ if (p->xpc->xp_context == EXPAND_USER_LIST
+ || p->xpc->xp_context == EXPAND_USER_DEFINED) {
+ size_t buflen = strlen(cmd_compl) + strlen(p->xpc->xp_arg) + 2;
+ char *buffer = xmalloc(buflen);
+ snprintf(buffer, buflen, "%s,%s", cmd_compl, p->xpc->xp_arg);
+ return buffer;
+ }
+
+ return xstrdup(cmd_compl);
}
/// "getcmdcompltype()" function
@@ -4219,7 +4169,8 @@ void f_setcmdline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
}
- rettv->vval.v_number = set_cmdline_str(argvars[0].vval.v_string, pos);
+ // Use tv_get_string() to handle a NULL string like an empty string.
+ rettv->vval.v_number = set_cmdline_str(tv_get_string(&argvars[0]), pos);
}
/// "setcmdpos()" function
@@ -4254,18 +4205,28 @@ int get_list_range(char **str, int *num1, int *num2)
*str = skipwhite((*str));
if (**str == '-' || ascii_isdigit(**str)) { // parse "from" part of range
- vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, false);
+ vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, false, NULL);
*str += len;
+ // overflow
+ if (num > INT_MAX) {
+ return FAIL;
+ }
+
*num1 = (int)num;
first = true;
}
*str = skipwhite((*str));
if (**str == ',') { // parse "to" part of range
*str = skipwhite((*str) + 1);
- vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, false);
+ vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, false, NULL);
if (len > 0) {
- *num2 = (int)num;
*str = skipwhite((*str) + len);
+ // overflow
+ if (num > INT_MAX) {
+ return FAIL;
+ }
+
+ *num2 = (int)num;
} else if (!first) { // no number given at all
return FAIL;
}
@@ -4282,14 +4243,12 @@ void cmdline_init(void)
/// Check value of 'cedit' and set cedit_key.
/// Returns NULL if value is OK, error message otherwise.
-char *check_cedit(void)
+const char *did_set_cedit(optset_T *args)
{
- int n;
-
if (*p_cedit == NUL) {
cedit_key = -1;
} else {
- n = string_to_key(p_cedit);
+ int n = string_to_key(p_cedit);
if (vim_isprintc(n)) {
return e_invarg;
}
@@ -4309,9 +4268,7 @@ static int open_cmdwin(void)
bufref_T old_curbuf;
bufref_T bufref;
win_T *old_curwin = curwin;
- win_T *wp;
int i;
- linenr_T lnum;
garray_T winsizes;
char typestr[2];
int save_restart_edit = restart_edit;
@@ -4351,6 +4308,7 @@ static int open_cmdwin(void)
// Set "cmdwin_type" before any autocommands may mess things up.
cmdwin_type = get_cmdline_type();
cmdwin_level = ccline.level;
+ cmdwin_old_curwin = old_curwin;
// Create empty command-line buffer.
if (buf_open_scratch(0, _("[Command Line]")) == FAIL) {
@@ -4358,10 +4316,11 @@ static int open_cmdwin(void)
win_close(curwin, true, false);
ga_clear(&winsizes);
cmdwin_type = 0;
+ cmdwin_old_curwin = NULL;
return Ctrl_C;
}
// Command-line buffer has bufhidden=wipe, unlike a true "scratch" buffer.
- set_option_value_give_err("bh", 0L, "wipe", OPT_LOCAL);
+ set_option_value_give_err("bh", STATIC_CSTR_AS_OPTVAL("wipe"), OPT_LOCAL);
curbuf->b_p_ma = true;
curwin->w_p_fen = false;
curwin->w_p_rl = cmdmsg_rl;
@@ -4379,7 +4338,7 @@ static int open_cmdwin(void)
add_map("<Tab>", "<C-X><C-V>", MODE_INSERT, true);
add_map("<Tab>", "a<C-X><C-V>", MODE_NORMAL, true);
}
- set_option_value_give_err("ft", 0L, "vim", OPT_LOCAL);
+ set_option_value_give_err("ft", STATIC_CSTR_AS_OPTVAL("vim"), OPT_LOCAL);
}
curbuf->b_ro_locked--;
@@ -4392,13 +4351,13 @@ static int open_cmdwin(void)
if (get_hislen() > 0 && histtype != HIST_INVALID) {
i = *get_hisidx(histtype);
if (i >= 0) {
- lnum = 0;
+ linenr_T lnum = 0;
do {
if (++i == get_hislen()) {
i = 0;
}
if (get_histentry(histtype)[i].hisstr != NULL) {
- ml_append(lnum++, get_histentry(histtype)[i].hisstr, (colnr_T)0, false);
+ ml_append(lnum++, get_histentry(histtype)[i].hisstr, 0, false);
}
} while (i != *get_hisidx(histtype));
}
@@ -4410,7 +4369,7 @@ static int open_cmdwin(void)
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
curwin->w_cursor.col = ccline.cmdpos;
changed_line_abv_curs();
- invalidate_botline();
+ invalidate_botline(curwin);
if (ui_has(kUICmdline)) {
ccline.redraw_state = kCmdRedrawNone;
ui_call_cmdline_hide(ccline.level);
@@ -4454,6 +4413,7 @@ static int open_cmdwin(void)
cmdwin_type = 0;
cmdwin_level = 0;
+ cmdwin_old_curwin = NULL;
exmode_active = save_exmode;
@@ -4463,6 +4423,7 @@ static int open_cmdwin(void)
cmdwin_result = Ctrl_C;
emsg(_("E199: Active window or buffer deleted"));
} else {
+ win_T *wp;
// autocmds may abort script processing
if (aborting() && cmdwin_result != K_IGNORE) {
cmdwin_result = Ctrl_C;
@@ -4500,7 +4461,8 @@ static int open_cmdwin(void)
ccline.cmdlen = (int)strlen(ccline.cmdbuff);
ccline.cmdbufflen = ccline.cmdlen + 1;
ccline.cmdpos = curwin->w_cursor.col;
- if (ccline.cmdpos > ccline.cmdlen) {
+ // If the cursor is on the last character, it probably should be after it.
+ if (ccline.cmdpos == ccline.cmdlen - 1 || ccline.cmdpos > ccline.cmdlen) {
ccline.cmdpos = ccline.cmdlen;
}
if (cmdwin_result == K_IGNORE) {
@@ -4569,39 +4531,37 @@ bool is_in_cmdwin(void)
char *script_get(exarg_T *const eap, size_t *const lenp)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC
{
- const char *const cmd = (const char *)eap->arg;
+ char *cmd = eap->arg;
if (cmd[0] != '<' || cmd[1] != '<' || eap->getline == NULL) {
*lenp = strlen(eap->arg);
return eap->skip ? NULL : xmemdupz(eap->arg, *lenp);
}
+ cmd += 2;
garray_T ga = { .ga_data = NULL, .ga_len = 0 };
+
+ list_T *const l = heredoc_get(eap, cmd, true);
+ if (l == NULL) {
+ return NULL;
+ }
+
if (!eap->skip) {
ga_init(&ga, 1, 0x400);
}
- const char *const end_pattern = (cmd[2] != NUL ? (const char *)skipwhite(cmd + 2) : ".");
- for (;;) {
- char *const theline = eap->getline(eap->cstack->cs_looplevel > 0 ? -1 : NUL, eap->cookie, 0,
- true);
-
- if (theline == NULL || strcmp(end_pattern, theline) == 0) {
- xfree(theline);
- break;
- }
-
+ TV_LIST_ITER_CONST(l, li, {
if (!eap->skip) {
- ga_concat(&ga, theline);
+ ga_concat(&ga, tv_get_string(TV_LIST_ITEM_TV(li)));
ga_append(&ga, '\n');
}
- xfree(theline);
- }
+ });
*lenp = (size_t)ga.ga_len; // Set length without trailing NUL.
if (!eap->skip) {
ga_append(&ga, NUL);
}
+ tv_list_free(l);
return (char *)ga.ga_data;
}