diff options
-rw-r--r-- | cmake.deps/CMakeLists.txt | 4 | ||||
-rwxr-xr-x | src/nvim/CMakeLists.txt | 7 | ||||
-rw-r--r-- | src/nvim/api/command.c | 49 | ||||
-rw-r--r-- | src/nvim/autocmd.c | 6 | ||||
-rw-r--r-- | src/nvim/buffer.c | 4 | ||||
-rw-r--r-- | src/nvim/eval/funcs.c | 323 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 1 | ||||
-rw-r--r-- | src/nvim/indent_c.c | 2 | ||||
-rw-r--r-- | src/nvim/insexpand.c | 468 | ||||
-rw-r--r-- | src/nvim/message.c | 38 | ||||
-rw-r--r-- | src/nvim/option.c | 35 | ||||
-rw-r--r-- | src/nvim/quickfix.c | 24 | ||||
-rw-r--r-- | src/nvim/spellfile.c | 144 | ||||
-rw-r--r-- | src/nvim/testdir/test_autocmd.vim | 51 | ||||
-rw-r--r-- | src/nvim/testdir/test_messages.vim | 11 | ||||
-rw-r--r-- | src/nvim/testdir/test_quickfix.vim | 8 | ||||
-rw-r--r-- | src/nvim/window.c | 219 | ||||
-rw-r--r-- | test/functional/legacy/messages_spec.lua | 23 |
18 files changed, 812 insertions, 605 deletions
diff --git a/cmake.deps/CMakeLists.txt b/cmake.deps/CMakeLists.txt index 07f414b431..0930d4ce2b 100644 --- a/cmake.deps/CMakeLists.txt +++ b/cmake.deps/CMakeLists.txt @@ -159,8 +159,8 @@ set(MSGPACK_URL https://github.com/msgpack/msgpack-c/releases/download/c-4.0.0/m set(MSGPACK_SHA256 420fe35e7572f2a168d17e660ef981a589c9cbe77faa25eb34a520e1fcc032c8) # https://github.com/LuaJIT/LuaJIT/tree/v2.1 -set(LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/50936d784474747b4569d988767f1b5bab8bb6d0.tar.gz) -set(LUAJIT_SHA256 4d44e4709130b031c1c2c81cf5c102dfce877bf454409dabba03249e18870e66) +set(LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/e1339aed3db2fb8488a170383fc456fe04879709.tar.gz) +set(LUAJIT_SHA256 72f4b0cc90800a92c8019947a8593d6295bbb5e3d10f589a3c75e1950d1d6c90) set(LUA_URL https://www.lua.org/ftp/lua-5.1.5.tar.gz) set(LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333) diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index f5f98a2b3d..4e608b8264 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -160,9 +160,7 @@ list(REMOVE_ITEM NVIM_SOURCES ${to_remove}) set(CONV_SOURCES screen.c spell.c - spellfile.c - syntax.c - window.c) + syntax.c) foreach(sfile ${CONV_SOURCES}) if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/${sfile}") message(FATAL_ERROR "${sfile} doesn't exist (it was added to CONV_SOURCES)") @@ -176,9 +174,6 @@ if(NOT MSVC) # xdiff, mpack, lua-cjson: inlined external project, we don't maintain it. #9306 set_source_files_properties( ${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion -Wno-missing-noreturn -Wno-missing-format-attribute -Wno-double-promotion") - - set_source_files_properties( - eval/funcs.c PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion") endif() if(NOT "${MIN_LOG_LEVEL}" MATCHES "^$") diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index 56ca624232..96e643f1fe 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -306,7 +306,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error char *cmdline = NULL; char *cmdname = NULL; - char **args = NULL; + ArrayOf(String) args; size_t argc = 0; String retv = (String)STRING_INIT; @@ -416,18 +416,12 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error VALIDATION_ERROR("Incorrect number of arguments supplied"); } - if (argc != 0) { - args = xcalloc(argc, sizeof(char *)); - - for (size_t i = 0; i < argc; i++) { - args[i] = string_to_cstr(cmd->args.data.array.items[i].data.string); - } - } + args = cmd->args.data.array; } // Simply pass the first argument (if it exists) as the arg pointer to `set_cmd_addr_type()` // since it only ever checks the first argument. - set_cmd_addr_type(&ea, argc > 0 ? args[0] : NULL); + set_cmd_addr_type(&ea, argc > 0 ? args.items[0].data.string.data : NULL); if (HAS_KEY(cmd->range)) { if (!(ea.argt & EX_RANGE)) { @@ -676,10 +670,6 @@ end: xfree(cmdname); xfree(ea.args); xfree(ea.arglens); - for (size_t i = 0; i < argc; i++) { - xfree(args[i]); - } - xfree(args); return retv; @@ -704,12 +694,11 @@ static bool string_iswhite(String str) } /// Build cmdline string for command, used by `nvim_cmd()`. -/// -/// @return OK or FAIL. -static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdinfo, char **args, - size_t argc) +static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdinfo, + ArrayOf(String) args, size_t argc) { StringBuilder cmdline = KV_INITIAL_VALUE; + kv_resize(cmdline, 32); // Make it big enough to handle most typical commands // Add command modifiers if (cmdinfo->cmdmod.cmod_tab != 0) { @@ -779,11 +768,11 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin // Keep the index of the position where command name starts, so eap->cmd can point to it. size_t cmdname_idx = cmdline.size; - kv_printf(cmdline, "%s", eap->cmd); + kv_concat(cmdline, eap->cmd); // Command bang. if (eap->argt & EX_BANG && eap->forceit) { - kv_printf(cmdline, "!"); + kv_concat(cmdline, "!"); } // Command register. @@ -791,29 +780,35 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin kv_printf(cmdline, " %c", eap->regname); } - // Iterate through each argument and store the starting index and length of each argument - size_t *argidx = xcalloc(argc, sizeof(size_t)); eap->argc = argc; eap->arglens = xcalloc(argc, sizeof(size_t)); + size_t argstart_idx = cmdline.size; for (size_t i = 0; i < argc; i++) { - argidx[i] = cmdline.size + 1; // add 1 to account for the space. - eap->arglens[i] = STRLEN(args[i]); - kv_printf(cmdline, " %s", args[i]); + String s = args.items[i].data.string; + eap->arglens[i] = s.size; + kv_concat(cmdline, " "); + kv_concat_len(cmdline, s.data, s.size); } + // Done appending to cmdline, ensure it is NUL terminated + kv_push(cmdline, NUL); + // Now that all the arguments are appended, use the command index and argument indices to set the // values of eap->cmd, eap->arg and eap->args. eap->cmd = cmdline.items + cmdname_idx; eap->args = xcalloc(argc, sizeof(char *)); + size_t offset = argstart_idx; for (size_t i = 0; i < argc; i++) { - eap->args[i] = cmdline.items + argidx[i]; + offset++; // Account for space + eap->args[i] = cmdline.items + offset; + offset += eap->arglens[i]; } // If there isn't an argument, make eap->arg point to end of cmdline. - eap->arg = argc > 0 ? eap->args[0] : cmdline.items + cmdline.size; + eap->arg = argc > 0 ? eap->args[0] : + cmdline.items + cmdline.size - 1; // Subtract 1 to account for NUL // Finally, make cmdlinep point to the cmdline string. *cmdlinep = cmdline.items; - xfree(argidx); // Replace, :make and :grep with 'makeprg' and 'grepprg'. char *p = replace_makeprg(eap, eap->arg, cmdlinep); diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index 73c2cda92b..2b4c9c5b9c 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -1837,9 +1837,13 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force } ap->last = true; + // Make sure cursor and topline are valid. The first time the current + // values are saved, restored by reset_lnums(). When nested only the + // values are corrected when needed. if (nesting == 1) { - // make sure cursor and topline are valid check_lnums(true); + } else { + check_lnums_nested(true); } // Execute the autocmd. The `getnextac` callback handles iteration. diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 10ce893fe8..328a72476a 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -3470,7 +3470,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, int use_san // Proceed character by character through the statusline format string // fmt_p is the current position in the input buffer - for (char *fmt_p = usefmt; *fmt_p;) { + for (char *fmt_p = usefmt; *fmt_p != NUL;) { if (curitem == (int)stl_items_len) { size_t new_len = stl_items_len * 3 / 2; @@ -3484,7 +3484,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, int use_san stl_items_len = new_len; } - if (*fmt_p != NUL && *fmt_p != '%') { + if (*fmt_p != '%') { prevchar_isflag = prevchar_isitem = false; } diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index fb59a3da4c..255a58fede 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -215,12 +215,11 @@ int call_internal_method(const char_u *const fname, const int argcount, typval_T } typval_T argv[MAX_FUNC_ARGS + 1]; - const ptrdiff_t base_index - = fdef->base_arg == BASE_LAST ? argcount : fdef->base_arg - 1; - memcpy(argv, argvars, base_index * sizeof(typval_T)); + const ptrdiff_t base_index = fdef->base_arg == BASE_LAST ? argcount : fdef->base_arg - 1; + memcpy(argv, argvars, (size_t)base_index * sizeof(typval_T)); argv[base_index] = *basetv; memcpy(argv + base_index + 1, argvars + base_index, - (argcount - base_index) * sizeof(typval_T)); + (size_t)(argcount - base_index) * sizeof(typval_T)); argv[argcount + 1].v_type = VAR_UNKNOWN; fdef->func(argv, rettv, fdef->data); @@ -328,7 +327,7 @@ static void f_add(typval_T *argvars, typval_T *rettv, FunPtr fptr) const varnumber_T n = tv_get_number_chk(&argvars[1], &error); if (!error) { - ga_append(&b->bv_ga, (int)n); + ga_append(&b->bv_ga, (char)n); tv_copy(&argvars[0], rettv); } } @@ -432,7 +431,7 @@ static void f_argv(typval_T *argvars, typval_T *rettv, FunPtr fptr) } rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; - int idx = tv_get_number_chk(&argvars[0], NULL); + int idx = (int)tv_get_number_chk(&argvars[0], NULL); if (arglist != NULL && idx >= 0 && idx < argcount) { rettv->vval.v_string = xstrdup((const char *)alist_name(&arglist[idx])); } else if (idx == -1) { @@ -833,7 +832,7 @@ static void f_chanclose(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } const char *error; - rettv->vval.v_number = channel_close(argvars[0].vval.v_number, part, &error); + rettv->vval.v_number = channel_close((uint64_t)argvars[0].vval.v_number, part, &error); if (!rettv->vval.v_number) { emsg(error); } @@ -861,7 +860,7 @@ static void f_chansend(typval_T *argvars, typval_T *rettv, FunPtr fptr) const blob_T *const b = argvars[1].vval.v_blob; input_len = tv_blob_len(b); if (input_len > 0) { - input = xmemdup(b->bv_ga.ga_data, input_len); + input = xmemdup(b->bv_ga.ga_data, (size_t)input_len); } } else { input = save_tv_as_string(&argvars[1], &input_len, false); @@ -872,9 +871,9 @@ static void f_chansend(typval_T *argvars, typval_T *rettv, FunPtr fptr) // or there is no input to send. return; } - uint64_t id = argvars[0].vval.v_number; + uint64_t id = (uint64_t)argvars[0].vval.v_number; const char *error = NULL; - rettv->vval.v_number = channel_send(id, input, input_len, true, &error); + rettv->vval.v_number = (varnumber_T)channel_send(id, input, (size_t)input_len, true, &error); if (error) { emsg(error); } @@ -1078,7 +1077,7 @@ static void f_confirm(typval_T *argvars, typval_T *rettv, FunPtr fptr) error = true; } if (argvars[2].v_type != VAR_UNKNOWN) { - def = tv_get_number_chk(&argvars[2], &error); + def = (int)tv_get_number_chk(&argvars[2], &error); if (argvars[3].v_type != VAR_UNKNOWN) { typestr = tv_get_string_buf_chk(&argvars[3], buf2); if (typestr == NULL) { @@ -1125,7 +1124,7 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) bool error = false; if (argvars[2].v_type != VAR_UNKNOWN) { - ic = tv_get_number_chk(&argvars[2], &error); + ic = (int)tv_get_number_chk(&argvars[2], &error); } if (argvars[0].v_type == VAR_STRING) { @@ -1163,7 +1162,7 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[3].v_type != VAR_UNKNOWN) { idx = tv_get_number_chk(&argvars[3], &error); if (!error) { - li = tv_list_find(l, idx); + li = tv_list_find(l, (int)idx); if (li == NULL) { semsg(_(e_listidx), (int64_t)idx); } @@ -1236,7 +1235,7 @@ static void f_ctxget(typval_T *argvars, typval_T *rettv, FunPtr fptr) { size_t index = 0; if (argvars[0].v_type == VAR_NUMBER) { - index = argvars[0].vval.v_number; + index = (size_t)argvars[0].vval.v_number; } else if (argvars[0].v_type != VAR_UNKNOWN) { semsg(_(e_invarg2), "expected nothing or a Number as an argument"); return; @@ -1304,7 +1303,7 @@ static void f_ctxset(typval_T *argvars, typval_T *rettv, FunPtr fptr) size_t index = 0; if (argvars[1].v_type == VAR_NUMBER) { - index = argvars[1].vval.v_number; + index = (size_t)argvars[1].vval.v_number; } else if (argvars[1].v_type != VAR_UNKNOWN) { semsg(_(e_invarg2), "expected nothing or a Number as second argument"); return; @@ -1338,7 +1337,7 @@ static void f_ctxset(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_ctxsize(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = ctx_size(); + rettv->vval.v_number = (varnumber_T)ctx_size(); } /// Set the cursor position. @@ -1372,7 +1371,7 @@ static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol) line = tv_get_lnum(argvars); col = (long)tv_get_number_chk(&argvars[1], NULL); if (charcol) { - col = buf_charidx_to_byteidx(curbuf, line, col) + 1; + col = buf_charidx_to_byteidx(curbuf, (linenr_T)line, (int)col) + 1; } if (argvars[2].v_type != VAR_UNKNOWN) { coladd = (long)tv_get_number_chk(&argvars[2], NULL); @@ -1385,12 +1384,12 @@ static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol) return; // type error; errmsg already given } if (line > 0) { - curwin->w_cursor.lnum = line; + curwin->w_cursor.lnum = (linenr_T)line; } if (col > 0) { - curwin->w_cursor.col = col - 1; + curwin->w_cursor.col = (colnr_T)col - 1; } - curwin->w_cursor.coladd = coladd; + curwin->w_cursor.coladd = (colnr_T)coladd; // Make sure the cursor is in a valid position. check_cursor(); @@ -1442,7 +1441,7 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr) int noref = 0; if (argvars[1].v_type != VAR_UNKNOWN) { - noref = tv_get_number_chk(&argvars[1], NULL); + noref = (int)tv_get_number_chk(&argvars[1], NULL); } if (noref < 0 || noref > 1) { emsg(_(e_invarg)); @@ -1619,7 +1618,7 @@ static void f_deletebufline(typval_T *argvars, typval_T *rettv, FunPtr fptr) FOR_ALL_TAB_WINDOWS(tp, wp) { if (wp->w_buffer == buf) { if (wp->w_cursor.lnum > last) { - wp->w_cursor.lnum -= count; + wp->w_cursor.lnum -= (linenr_T)count; } else if (wp->w_cursor.lnum > first) { wp->w_cursor.lnum = first; } @@ -1656,7 +1655,7 @@ static void f_diff_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T lnum = tv_get_lnum(argvars); static linenr_T prev_lnum = 0; - static int changedtick = 0; + static varnumber_T changedtick = 0; static int fnum = 0; static int change_start = 0; static int change_end = 0; @@ -1693,7 +1692,7 @@ static void f_diff_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (hlID == HLF_CHD || hlID == HLF_TXD) { - col = tv_get_number(&argvars[1]) - 1; // Ignore type error in {col}. + col = (int)tv_get_number(&argvars[1]) - 1; // Ignore type error in {col}. if (col >= change_start && col <= change_end) { hlID = HLF_TXD; // Changed text. } else { @@ -1764,7 +1763,7 @@ static void f_environ(typval_T *argvars, typval_T *rettv, FunPtr fptr) os_copy_fullenv(env, env_size); - for (ssize_t i = env_size - 1; i >= 0; i--) { + for (ssize_t i = (ssize_t)env_size - 1; i >= 0; i--) { const char *str = env[i]; const char * const end = strchr(str + (str[0] == '=' ? 1 : 0), '='); @@ -1792,9 +1791,7 @@ static void f_environ(typval_T *argvars, typval_T *rettv, FunPtr fptr) xfree(key); continue; } - tv_dict_add_str(rettv->vval.v_dict, - key, len, - value); + tv_dict_add_str(rettv->vval.v_dict, key, (size_t)len, value); xfree(key); } os_free_fullenv(env); @@ -1973,7 +1970,7 @@ static void f_win_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; - int id = tv_get_number(argvars); + int id = (int)tv_get_number(argvars); tabpage_T *tp; win_T *wp = win_id2wp_tp(id, &tp); if (wp != NULL && tp != NULL) { @@ -2209,7 +2206,7 @@ static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (before == tv_list_len(l1)) { item = NULL; } else { - item = tv_list_find(l1, before); + item = tv_list_find(l1, (int)before); if (item == NULL) { semsg(_(e_listidx), (int64_t)before); return; @@ -2326,7 +2323,7 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) } if (argvars[2].v_type != VAR_UNKNOWN) { - count = tv_get_number_chk(&argvars[2], &error); + count = (int)tv_get_number_chk(&argvars[2], &error); } } } @@ -2521,7 +2518,7 @@ static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } } - unsigned long count = (unsigned long)foldend - foldstart + 1; + unsigned long count = (unsigned long)foldend - (unsigned long)foldstart + 1; txt = NGETTEXT("+-%s%3ld line: ", "+-%s%3ld lines: ", count); r = xmalloc(STRLEN(txt) + STRLEN(dashes) // for %s @@ -2557,7 +2554,7 @@ static void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr) foldinfo_T info = fold_info(curwin, lnum); if (info.fi_lines > 0) { - text = get_foldtext(curwin, lnum, lnum + info.fi_lines - 1, info, buf); + text = get_foldtext(curwin, lnum, lnum + (linenr_T)info.fi_lines - 1, info, buf); if (text == buf) { text = vim_strsave(text); } @@ -2605,7 +2602,7 @@ static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].v_type == VAR_BLOB) { bool error = false; - int idx = tv_get_number_chk(&argvars[1], &error); + int idx = (int)tv_get_number_chk(&argvars[1], &error); if (!error) { rettv->v_type = VAR_NUMBER; @@ -2623,7 +2620,7 @@ static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) if ((l = argvars[0].vval.v_list) != NULL) { bool error = false; - li = tv_list_find(l, tv_get_number_chk(&argvars[1], &error)); + li = tv_list_find(l, (int)tv_get_number_chk(&argvars[1], &error)); if (!error && li != NULL) { tv = TV_LIST_ITEM_TV(li); } @@ -2813,7 +2810,7 @@ static void f_getchangelist(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].v_type == VAR_UNKNOWN) { buf = curbuf; } else { - vim_ignored = tv_get_number(&argvars[0]); // issue errmsg if type error + vim_ignored = (int)tv_get_number(&argvars[0]); // issue errmsg if type error emsg_off++; buf = tv_get_buf(&argvars[0], false); emsg_off--; @@ -2916,21 +2913,21 @@ static void getchar_common(typval_T *argvars, typval_T *rettv) if (mod_mask != 0) { temp[i++] = K_SPECIAL; temp[i++] = KS_MODIFIER; - temp[i++] = mod_mask; + temp[i++] = (char_u)mod_mask; } if (IS_SPECIAL(n)) { temp[i++] = K_SPECIAL; - temp[i++] = K_SECOND(n); + temp[i++] = (char_u)K_SECOND(n); temp[i++] = K_THIRD(n); } else { - i += utf_char2bytes(n, (char *)temp + i); + i += utf_char2bytes((int)n, (char *)temp + i); } assert(i < 10); temp[i++] = NUL; rettv->v_type = VAR_STRING; rettv->vval.v_string = (char *)vim_strsave(temp); - if (is_mouse_key(n)) { + if (is_mouse_key((int)n)) { int row = mouse_row; int col = mouse_col; int grid = mouse_grid; @@ -2975,7 +2972,7 @@ static void f_getcharstr(typval_T *argvars, typval_T *rettv, FunPtr fptr) int i = 0; if (n != 0) { - i += utf_char2bytes(n, (char *)temp); + i += utf_char2bytes((int)n, (char *)temp); } assert(i < 7); temp[i++] = NUL; @@ -3094,7 +3091,7 @@ static void f_getcmdtype(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; rettv->vval.v_string = xmallocz(1); - rettv->vval.v_string[0] = get_cmdline_type(); + rettv->vval.v_string[0] = (char)get_cmdline_type(); } /// "getcmdwintype()" function @@ -3103,7 +3100,7 @@ static void f_getcmdwintype(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; rettv->vval.v_string = xmallocz(1); - rettv->vval.v_string[0] = cmdwin_type; + rettv->vval.v_string[0] = (char)cmdwin_type; } /// "getcompletion()" function @@ -3143,7 +3140,7 @@ static void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (strcmp(type, "cmdline") == 0) { set_one_cmd_context(&xpc, pattern); xpc.xp_pattern_len = STRLEN(xpc.xp_pattern); - xpc.xp_col = STRLEN(pattern); + xpc.xp_col = (int)STRLEN(pattern); goto theend; } @@ -3224,7 +3221,7 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr) emsg(_(e_invarg)); return; } - scope_number[i] = argvars[i].vval.v_number; + scope_number[i] = (int)argvars[i].vval.v_number; // It is an error for the scope number to be less than `-1`. if (scope_number[i] < -1) { emsg(_(e_invarg)); @@ -3324,7 +3321,7 @@ static void f_getfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr) perm = xstrdup("---------"); for (int i = 0; i < 9; i++) { if (file_perm & (1 << (8 - i))) { - perm[i] = flags[i % 3]; + perm[i] = (char)flags[i % 3]; } } } @@ -3683,7 +3680,7 @@ static void f_getwininfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) tv_list_alloc_ret(rettv, kListLenMayKnow); if (argvars[0].v_type != VAR_UNKNOWN) { - wparg = win_id2wp(tv_get_number(&argvars[0])); + wparg = win_id2wp((int)tv_get_number(&argvars[0])); if (wparg == NULL) { return; } @@ -3736,10 +3733,10 @@ static void f_wait(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - int timeout = argvars[0].vval.v_number; + int timeout = (int)argvars[0].vval.v_number; typval_T expr = argvars[1]; int interval = argvars[2].v_type == VAR_NUMBER - ? argvars[2].vval.v_number + ? (int)argvars[2].vval.v_number : 200; // Default. TimeWatcher *tw = xmalloc(sizeof(TimeWatcher)); @@ -3747,7 +3744,7 @@ static void f_wait(typval_T *argvars, typval_T *rettv, FunPtr fptr) time_watcher_init(&main_loop, tw, NULL); tw->events = main_loop.events; tw->blockable = true; - time_watcher_start(tw, dummy_timer_due_cb, interval, interval); + time_watcher_start(tw, dummy_timer_due_cb, (uint64_t)interval, (uint64_t)interval); typval_T argv = TV_INITIAL_VALUE; typval_T exprval = TV_INITIAL_VALUE; @@ -3855,7 +3852,7 @@ static void f_win_splitmove(typval_T *argvars, typval_T *rettv, FunPtr fptr) if ((di = tv_dict_find(d, "rightbelow", -1)) != NULL) { flags |= tv_get_number(&di->di_tv) ? WSP_BELOW : WSP_ABOVE; } - size = tv_dict_get_number(d, "size"); + size = (int)tv_dict_get_number(d, "size"); } win_move_into_split(wp, targetwin, size, flags); @@ -4124,7 +4121,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) }; // XXX: eval_has_provider() may shell out :( - const int save_shell_error = get_vim_var_nr(VV_SHELL_ERROR); + const int save_shell_error = (int)get_vim_var_nr(VV_SHELL_ERROR); bool n = false; const char *const name = tv_get_string(&argvars[0]); for (size_t i = 0; i < ARRAY_SIZE(has_list); i++) { @@ -4239,7 +4236,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr) emsg(_(e_invarg)); return; } - scope_number[i] = argvars[i].vval.v_number; + scope_number[i] = (int)argvars[i].vval.v_number; if (scope_number[i] < -1) { emsg(_(e_invarg)); return; @@ -4455,7 +4452,7 @@ static void f_index(typval_T *argvars, typval_T *rettv, FunPtr fptr) int start = 0; if (argvars[2].v_type != VAR_UNKNOWN) { - start = tv_get_number_chk(&argvars[2], &error); + start = (int)tv_get_number_chk(&argvars[2], &error); if (error) { return; } @@ -4473,7 +4470,7 @@ static void f_index(typval_T *argvars, typval_T *rettv, FunPtr fptr) for (idx = start; idx < tv_blob_len(b); idx++) { typval_T tv; tv.v_type = VAR_NUMBER; - tv.vval.v_number = tv_blob_get(b, idx); + tv.vval.v_number = tv_blob_get(b, (int)idx); if (tv_equal(&tv, &argvars[1], ic, false)) { rettv->vval.v_number = idx; return; @@ -4491,11 +4488,11 @@ static void f_index(typval_T *argvars, typval_T *rettv, FunPtr fptr) bool error = false; // Start at specified item. - idx = tv_list_uidx(l, tv_get_number_chk(&argvars[2], &error)); + idx = tv_list_uidx(l, (int)tv_get_number_chk(&argvars[2], &error)); if (error || idx == -1) { item = NULL; } else { - item = tv_list_find(l, idx); + item = tv_list_find(l, (int)idx); assert(item != NULL); } if (argvars[3].v_type != VAR_UNKNOWN) { @@ -4623,7 +4620,7 @@ static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } } - const int val = tv_get_number_chk(&argvars[1], &error); + const int val = (int)tv_get_number_chk(&argvars[1], &error); if (error) { return; } @@ -4634,8 +4631,8 @@ static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr) ga_grow(&b->bv_ga, 1); char_u *const p = (char_u *)b->bv_ga.ga_data; - memmove(p + before + 1, p + before, (size_t)len - before); - *(p + before) = val; + memmove(p + before + 1, p + before, (size_t)(len - before)); + *(p + before) = (char_u)val; b->bv_ga.ga_len++; tv_copy(&argvars[0], rettv); @@ -4654,7 +4651,7 @@ static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr) listitem_T *item = NULL; if (before != tv_list_len(l)) { - item = tv_list_find(l, before); + item = tv_list_find(l, (int)before); if (item == NULL) { semsg(_(e_listidx), (int64_t)before); l = NULL; @@ -4751,8 +4748,8 @@ static void f_id(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const int len = vim_vsnprintf_typval(NULL, 0, "%p", dummy_ap, argvars); rettv->v_type = VAR_STRING; - rettv->vval.v_string = xmalloc(len + 1); - vim_vsnprintf_typval(rettv->vval.v_string, len + 1, "%p", dummy_ap, argvars); + rettv->vval.v_string = xmalloc((size_t)len + 1); + vim_vsnprintf_typval(rettv->vval.v_string, (size_t)len + 1, "%p", dummy_ap, argvars); } /// "jobpid(id)" function @@ -4770,7 +4767,7 @@ static void f_jobpid(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - Channel *data = find_job(argvars[0].vval.v_number, true); + Channel *data = find_job((uint64_t)argvars[0].vval.v_number, true); if (!data) { return; } @@ -4796,7 +4793,7 @@ static void f_jobresize(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - Channel *data = find_job(argvars[0].vval.v_number, true); + Channel *data = find_job((uint64_t)argvars[0].vval.v_number, true); if (!data) { return; } @@ -4806,8 +4803,8 @@ static void f_jobresize(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - pty_process_resize(&data->stream.pty, argvars[1].vval.v_number, - argvars[2].vval.v_number); + pty_process_resize(&data->stream.pty, (uint16_t)argvars[1].vval.v_number, + (uint16_t)argvars[2].vval.v_number); rettv->vval.v_number = 1; } @@ -4922,7 +4919,7 @@ static dict_T *create_environment(const dictitem_T *job_env, const bool clear_en i < ARRAY_SIZE(required_env_vars) && required_env_vars[i]; i++) { size_t len = strlen(required_env_vars[i]); - dictitem_T *dv = tv_dict_find(env, required_env_vars[i], len); + dictitem_T *dv = tv_dict_find(env, required_env_vars[i], (ptrdiff_t)len); if (!dv) { const char *env_var = os_getenv(required_env_vars[i]); if (env_var) { @@ -5071,7 +5068,7 @@ static void f_jobstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - Channel *data = find_job(argvars[0].vval.v_number, false); + Channel *data = find_job((uint64_t)argvars[0].vval.v_number, false); if (!data) { return; } @@ -5105,7 +5102,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr) ui_busy_start(); list_T *args = argvars[0].vval.v_list; - Channel **jobs = xcalloc(tv_list_len(args), sizeof(*jobs)); + Channel **jobs = xcalloc((size_t)tv_list_len(args), sizeof(*jobs)); MultiQueue *waiting_jobs = multiqueue_new_parent(loop_on_put, &main_loop); // Validate, prepare jobs for waiting. @@ -5113,7 +5110,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr) TV_LIST_ITER_CONST(args, arg, { Channel *chan = NULL; if (TV_LIST_ITEM_TV(arg)->v_type != VAR_NUMBER - || !(chan = find_channel(TV_LIST_ITEM_TV(arg)->vval.v_number)) + || !(chan = find_channel((uint64_t)TV_LIST_ITEM_TV(arg)->vval.v_number)) || chan->streamtype != kChannelStreamProc) { jobs[i] = NULL; // Invalid job. } else if (process_is_stopped(&chan->stream.proc)) { @@ -5136,7 +5133,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr) int remaining = -1; uint64_t before = 0; if (argvars[1].v_type == VAR_NUMBER && argvars[1].vval.v_number >= 0) { - remaining = argvars[1].vval.v_number; + remaining = (int)argvars[1].vval.v_number; before = os_hrtime(); } @@ -5272,7 +5269,7 @@ static void f_len(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void libcall_common(typval_T *argvars, typval_T *rettv, int out_type) { - rettv->v_type = out_type; + rettv->v_type = (VarType)out_type; if (out_type != VAR_NUMBER) { rettv->vval.v_string = NULL; } @@ -5293,7 +5290,7 @@ static void libcall_common(typval_T *argvars, typval_T *rettv, int out_type) // input variables char *str_in = (in_type == VAR_STRING) ? argvars[2].vval.v_string : NULL; - int int_in = argvars[2].vval.v_number; + int int_in = (int)argvars[2].vval.v_number; // output variables char **str_out = (out_type == VAR_STRING) ? &rettv->vval.v_string : NULL; @@ -5477,11 +5474,11 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, goto theend; } if (l != NULL) { - idx = tv_list_uidx(l, start); + idx = tv_list_uidx(l, (int)start); if (idx == -1) { goto theend; } - li = tv_list_find(l, idx); + li = tv_list_find(l, (int)idx); } else { if (start < 0) { start = 0; @@ -5493,7 +5490,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, // otherwise skip part of the string. Differs when pattern is "^" // or "\<". if (argvars[3].v_type != VAR_UNKNOWN) { - startcol = start; + startcol = (colnr_T)start; } else { str += start; len -= start; @@ -5737,7 +5734,7 @@ static void f_mkdir(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[1].v_type != VAR_UNKNOWN) { if (argvars[2].v_type != VAR_UNKNOWN) { - prot = tv_get_number_chk(&argvars[2], NULL); + prot = (int)tv_get_number_chk(&argvars[2], NULL); if (prot == -1) { return; } @@ -5905,7 +5902,7 @@ static void msgpackparse_unpack_blob(const blob_T *const blob, list_T *const ret msgpack_unpacked_init(&unpacked); for (size_t offset = 0; offset < (size_t)len;) { const msgpack_unpack_return result - = msgpack_unpack_next(&unpacked, blob->bv_ga.ga_data, len, &offset); + = msgpack_unpack_next(&unpacked, blob->bv_ga.ga_data, (size_t)len, &offset); if (msgpackparse_convert_item(unpacked.data, result, ret_list, true) != OK) { break; @@ -6051,9 +6048,9 @@ static void f_printf(typval_T *argvars, typval_T *rettv, FunPtr fptr) const char *fmt = tv_get_string_buf(&argvars[0], buf); len = vim_vsnprintf_typval(NULL, 0, fmt, dummy_ap, argvars + 1); if (!did_emsg) { - char *s = xmalloc(len + 1); + char *s = xmalloc((size_t)len + 1); rettv->vval.v_string = s; - (void)vim_vsnprintf_typval(s, len + 1, fmt, dummy_ap, argvars + 1); + (void)vim_vsnprintf_typval(s, (size_t)len + 1, fmt, dummy_ap, argvars + 1); } did_emsg |= saved_did_emsg; } @@ -6197,7 +6194,7 @@ static void init_srand(uint32_t *const x) // Reading /dev/urandom doesn't work, fall back to time(). #endif // uncrustify:off - *x = time(NULL); + *x = (uint32_t)time(NULL); #ifndef MSWIN } #endif @@ -6275,10 +6272,10 @@ static void f_rand(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (tvw->v_type != VAR_NUMBER) { goto theend; } - uint32_t x = tvx->vval.v_number; - uint32_t y = tvy->vval.v_number; - uint32_t z = tvz->vval.v_number; - uint32_t w = tvw->vval.v_number; + uint32_t x = (uint32_t)tvx->vval.v_number; + uint32_t y = (uint32_t)tvy->vval.v_number; + uint32_t z = (uint32_t)tvz->vval.v_number; + uint32_t w = (uint32_t)tvw->vval.v_number; result = shuffle_xoshiro128starstar(&x, &y, &z, &w); @@ -6310,7 +6307,7 @@ static void f_srand(typval_T *argvars, typval_T *rettv, FunPtr fptr) init_srand(&x); } else { bool error = false; - x = tv_get_number_chk(&argvars[0], &error); + x = (uint32_t)tv_get_number_chk(&argvars[0], &error); if (error) { return; } @@ -6477,7 +6474,7 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) list_T *const l = tv_list_alloc_ret(rettv, kListLenUnknown); while (maxline < 0 || tv_list_len(l) < maxline) { - readlen = (int)fread(buf, 1, io_size, fd); + readlen = (int)fread(buf, 1, (size_t)io_size, fd); // This for loop processes what was read, but is also entered at end // of file so that either: @@ -6491,7 +6488,7 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) p++) { if (*p == '\n' || readlen <= 0) { char_u *s = NULL; - size_t len = p - start; + size_t len = (size_t)(p - start); // Finished a line. Remove CRs before NL. if (readlen > 0 && !binary) { @@ -6512,9 +6509,9 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) /* Change "prev" buffer to be the right size. This way * the bytes are only copied once, and very long lines are * allocated only once. */ - s = xrealloc(prev, prevlen + len + 1); + s = xrealloc(prev, (size_t)prevlen + len + 1); memcpy(s + prevlen, start, len); - s[prevlen + len] = NUL; + s[(size_t)prevlen + len] = NUL; prev = NULL; // the list will own the string prevlen = prevsize = 0; } @@ -6569,7 +6566,7 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) dest = buf; } if (readlen > p - buf + 1) { - memmove(dest, p + 1, readlen - (p - buf) - 1); + memmove(dest, p + 1, (size_t)readlen - (size_t)(p - buf) - 1); } readlen -= 3 - adjust_prevlen; prevlen -= adjust_prevlen; @@ -6596,10 +6593,10 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) long growmin = (long)((p - start) * 2 + prevlen); prevsize = grow50pc > growmin ? grow50pc : growmin; } - prev = xrealloc(prev, prevsize); + prev = xrealloc(prev, (size_t)prevsize); } // Add the line part to end of "prev". - memmove(prev + prevlen, start, p - start); + memmove(prev + prevlen, start, (size_t)(p - start)); prevlen += (long)(p - start); } } // while @@ -6648,7 +6645,7 @@ static void f_getreginfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) } (void)tv_dict_add_str(dict, S_LEN("regtype"), buf); - buf[0] = get_register_name(get_unname_register()); + buf[0] = (char)get_register_name(get_unname_register()); buf[1] = NUL; if (regname == '"') { (void)tv_dict_add_str(dict, S_LEN("points_to"), buf); @@ -6699,7 +6696,7 @@ static int list2proftime(typval_T *arg, proftime_T *tm) FUNC_ATTR_NONNULL_ALL union { struct { int32_t low, high; } split; proftime_T prof; - } u = { .split.high = n1, .split.low = n2 }; + } u = { .split.high = (int32_t)n1, .split.low = (int32_t)n2 }; *tm = u.prof; @@ -6816,15 +6813,15 @@ static void f_repeat(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (slen == 0) { return; } - const size_t len = slen * n; + const size_t len = slen * (size_t)n; // Detect overflow. - if (len / n != slen) { + if (len / (size_t)n != slen) { return; } char *const r = xmallocz(len); for (varnumber_T i = 0; i < n; i++) { - memmove(r + i * slen, p, slen); + memmove(r + (size_t)i * slen, p, slen); } rettv->vval.v_string = r; @@ -6938,9 +6935,9 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr) q = (char *)path_next_component(remain + 1); len = q - remain - (*q != NUL); const size_t p_len = strlen(p); - cpy = xmallocz(p_len + len); + cpy = xmallocz(p_len + (size_t)len); memcpy(cpy, p, p_len + 1); - xstrlcat(cpy + p_len, remain, len + 1); + xstrlcat(cpy + p_len, remain, (size_t)len + 1); xfree(p); p = cpy; @@ -7504,7 +7501,7 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) // Allocate extra memory for the argument vector and the NULL pointer int argvl = argsl + 2; - char **argv = xmalloc(sizeof(char_u *) * argvl); + char **argv = xmalloc(sizeof(char_u *) * (size_t)argvl); // Copy program name argv[0] = xstrdup(argvars[0].vval.v_string); @@ -7547,13 +7544,13 @@ static void f_rpcstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) } // if called with a job, stop it, else closes the channel - uint64_t id = argvars[0].vval.v_number; + uint64_t id = (uint64_t)argvars[0].vval.v_number; if (find_job(id, false)) { f_jobstop(argvars, rettv, NULL); } else { const char *error; - rettv->vval.v_number = channel_close(argvars[0].vval.v_number, - kChannelPartRpc, &error); + rettv->vval.v_number = + channel_close((uint64_t)argvars[0].vval.v_number, kChannelPartRpc, &error); if (!rettv->vval.v_number) { emsg(error); } @@ -7574,7 +7571,7 @@ static void f_screenattr(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (row < 0 || row >= grid->rows || col < 0 || col >= grid->cols) { c = -1; } else { - c = grid->attrs[grid->line_offset[row] + col]; + c = grid->attrs[grid->line_offset[row] + (size_t)col]; } rettv->vval.v_number = c; } @@ -7585,15 +7582,15 @@ static void f_screenchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) int c; ScreenGrid *grid; - int row = tv_get_number_chk(&argvars[0], NULL) - 1; - int col = tv_get_number_chk(&argvars[1], NULL) - 1; + int row = (int)tv_get_number_chk(&argvars[0], NULL) - 1; + int col = (int)tv_get_number_chk(&argvars[1], NULL) - 1; screenchar_adjust(&grid, &row, &col); if (row < 0 || row >= grid->rows || col < 0 || col >= grid->cols) { c = -1; } else { - c = utf_ptr2char((char *)grid->chars[grid->line_offset[row] + col]); + c = utf_ptr2char((char *)grid->chars[grid->line_offset[row] + (size_t)col]); } rettv->vval.v_number = c; } @@ -7602,8 +7599,8 @@ static void f_screenchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_screenchars(typval_T *argvars, typval_T *rettv, FunPtr fptr) { ScreenGrid *grid; - int row = tv_get_number_chk(&argvars[0], NULL) - 1; - int col = tv_get_number_chk(&argvars[1], NULL) - 1; + int row = (int)tv_get_number_chk(&argvars[0], NULL) - 1; + int col = (int)tv_get_number_chk(&argvars[1], NULL) - 1; screenchar_adjust(&grid, &row, &col); @@ -7612,7 +7609,7 @@ static void f_screenchars(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } int pcc[MAX_MCO]; - int c = utfc_ptr2char(grid->chars[grid->line_offset[row] + col], pcc); + int c = utfc_ptr2char(grid->chars[grid->line_offset[row] + (size_t)col], pcc); int composing_len = 0; while (pcc[composing_len] != 0) { composing_len++; @@ -7647,8 +7644,8 @@ static void f_screenpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - pos.lnum = tv_get_number(&argvars[1]); - pos.col = tv_get_number(&argvars[2]) - 1; + pos.lnum = (linenr_T)tv_get_number(&argvars[1]); + pos.col = (colnr_T)tv_get_number(&argvars[2]) - 1; pos.coladd = 0; textpos2screenpos(wp, &pos, &row, &scol, &ccol, &ecol, false); @@ -7671,8 +7668,8 @@ static void f_screenstring(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_STRING; ScreenGrid *grid; - int row = tv_get_number_chk(&argvars[0], NULL) - 1; - int col = tv_get_number_chk(&argvars[1], NULL) - 1; + int row = (int)tv_get_number_chk(&argvars[0], NULL) - 1; + int col = (int)tv_get_number_chk(&argvars[1], NULL) - 1; screenchar_adjust(&grid, &row, &col); @@ -7680,7 +7677,7 @@ static void f_screenstring(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - rettv->vval.v_string = (char *)vim_strsave(grid->chars[grid->line_offset[row] + col]); + rettv->vval.v_string = (char *)vim_strsave(grid->chars[grid->line_offset[row] + (size_t)col]); } /// "search()" function @@ -7778,8 +7775,8 @@ static int searchpair_cmn(typval_T *argvars, pos_T *match_pos) } } - retval = do_searchpair(spat, mpat, epat, dir, skip, - flags, match_pos, lnum_stop, time_limit); + retval = (int)do_searchpair(spat, mpat, epat, dir, skip, + flags, match_pos, (linenr_T)lnum_stop, time_limit); theend: p_ws = save_p_ws; @@ -8006,7 +8003,7 @@ static void f_serverlist(typval_T *argvars, typval_T *rettv, FunPtr fptr) char **addrs = server_address_list(&n); // Copy addrs into a linked list. - list_T *const l = tv_list_alloc_ret(rettv, n); + list_T *const l = tv_list_alloc_ret(rettv, (ptrdiff_t)n); for (size_t i = 0; i < n; i++) { tv_list_append_allocated_string(l, addrs[i]); } @@ -8387,7 +8384,7 @@ static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (strregname == NULL) { return; // Type error; errmsg already given. } - char regname = (uint8_t)(*strregname); + char regname = *strregname; if (regname == 0 || regname == '@') { regname = '"'; } @@ -8466,7 +8463,7 @@ static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) // First half: use for pointers to result lines; second half: use for // pointers to allocated copies. - char **lstval = xmalloc(sizeof(char *) * ((len + 1) * 2)); + char **lstval = xmalloc(sizeof(char *) * (((size_t)len + 1) * 2)); const char **curval = (const char **)lstval; char **allocval = lstval + len + 2; char **curallocval = allocval; @@ -8488,8 +8485,7 @@ static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) }); *curval++ = NULL; - write_reg_contents_lst(regname, (char_u **)lstval, append, yank_type, - block_len); + write_reg_contents_lst(regname, (char_u **)lstval, append, yank_type, (colnr_T)block_len); free_lstval: while (curallocval > allocval) { @@ -8501,8 +8497,8 @@ free_lstval: if (strval == NULL) { return; } - write_reg_contents_ex(regname, (const char_u *)strval, STRLEN(strval), - append, yank_type, block_len); + write_reg_contents_ex(regname, (const char_u *)strval, (ssize_t)STRLEN(strval), + append, yank_type, (colnr_T)block_len); } if (pointreg != 0) { get_yank_register(pointreg, YREG_YANK); @@ -8602,7 +8598,7 @@ static void f_shiftwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (col < 0) { return; // type error; errmsg already given } - rettv->vval.v_number = get_sw_value_col(curbuf, col); + rettv->vval.v_number = get_sw_value_col(curbuf, (colnr_T)col); return; } rettv->vval.v_number = get_sw_value(curbuf); @@ -8764,7 +8760,7 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr) break; } str += len; - capcol -= len; + capcol -= (int)len; len = 0; } } @@ -8773,7 +8769,7 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr) assert(len <= INT_MAX); tv_list_alloc_ret(rettv, 2); - tv_list_append_string(rettv->vval.v_list, word, len); + tv_list_append_string(rettv->vval.v_list, word, (ssize_t)len); tv_list_append_string(rettv->vval.v_list, (attr == HLF_SPB ? "bad" : attr == HLF_SPR ? "rare" @@ -8806,7 +8802,7 @@ static void f_spellsuggest(typval_T *argvars, typval_T *rettv, FunPtr fptr) const char *const str = tv_get_string(&argvars[0]); if (argvars[1].v_type != VAR_UNKNOWN) { - maxcount = tv_get_number_chk(&argvars[1], &typeerr); + maxcount = (int)tv_get_number_chk(&argvars[1], &typeerr); if (maxcount <= 0) { goto f_spellsuggest_return; } @@ -8978,7 +8974,7 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) int what = 0; if (argvars[1].v_type != VAR_UNKNOWN) { - base = tv_get_number(&argvars[1]); + base = (int)tv_get_number(&argvars[1]); if (base != 2 && base != 8 && base != 10 && base != 16) { emsg(_(e_invarg)); return; @@ -9089,7 +9085,7 @@ static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) break; } charidx--; - byteidx += utf_ptr2len(str + byteidx); + byteidx += (size_t)utf_ptr2len(str + byteidx); } } @@ -9147,7 +9143,7 @@ static void f_strchars(typval_T *argvars, typval_T *rettv, FunPtr fptr) int (*func_mb_ptr2char_adv)(const char_u **pp); if (argvars[1].v_type != VAR_UNKNOWN) { - skipcc = tv_get_number_chk(&argvars[1], NULL); + skipcc = (int)tv_get_number_chk(&argvars[1], NULL); } if (skipcc < 0 || skipcc > 1) { emsg(_(e_invarg)); @@ -9168,7 +9164,7 @@ static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) int col = 0; if (argvars[1].v_type != VAR_UNKNOWN) { - col = tv_get_number(&argvars[1]); + col = (int)tv_get_number(&argvars[1]); } rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, (char_u *)s) - col); @@ -9198,12 +9194,12 @@ static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) nchar--; } } else { - nbyte = nchar; + nbyte = (int)nchar; } } int len = 0; if (argvars[2].v_type != VAR_UNKNOWN) { - int charlen = tv_get_number(&argvars[2]); + int charlen = (int)tv_get_number(&argvars[2]); while (charlen > 0 && nbyte + len < (int)slen) { int off = nbyte + len; @@ -9215,7 +9211,7 @@ static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) charlen--; } } else { - len = slen - nbyte; // default: all bytes that are available. + len = (int)slen - nbyte; // default: all bytes that are available. } // Only return the overlap between the specified part and the actual @@ -9224,12 +9220,12 @@ static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) len += nbyte; nbyte = 0; } else if ((size_t)nbyte > slen) { - nbyte = slen; + nbyte = (int)slen; } if (len < 0) { len = 0; } else if (nbyte + len > (int)slen) { - len = slen - nbyte; + len = (int)slen - nbyte; } rettv->v_type = VAR_STRING; @@ -9251,7 +9247,7 @@ static void f_strpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) } else if (argvars[2].v_type != VAR_UNKNOWN) { len = tv_get_number(&argvars[2]); } else { - len = slen - n; // Default len: all bytes that are available. + len = (varnumber_T)slen - n; // Default len: all bytes that are available. } // Only return the overlap between the specified part and the actual @@ -9260,19 +9256,19 @@ static void f_strpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) len += n; n = 0; } else if (n > (varnumber_T)slen) { - n = slen; + n = (varnumber_T)slen; } if (len < 0) { len = 0; } else if (n + len > (varnumber_T)slen) { - len = slen - n; + len = (varnumber_T)slen - n; } if (argvars[2].v_type != VAR_UNKNOWN && argvars[3].v_type != VAR_UNKNOWN) { int off; // length in characters - for (off = n; off < (int)slen && len > 0; len--) { + for (off = (int)n; off < (int)slen && len > 0; len--) { off += utfc_ptr2len(p + off); } len = off - n; @@ -9380,7 +9376,7 @@ static void f_submatch(typval_T *argvars, typval_T *rettv, FunPtr fptr) int retList = 0; if (argvars[1].v_type != VAR_UNKNOWN) { - retList = tv_get_number_chk(&argvars[1], &error); + retList = (int)tv_get_number_chk(&argvars[1], &error); if (error) { return; } @@ -9453,7 +9449,7 @@ static void f_synID(typval_T *argvars, typval_T *rettv, FunPtr fptr) const colnr_T col = (colnr_T)tv_get_number(&argvars[1]) - 1; bool transerr = false; - const int trans = tv_get_number_chk(&argvars[2], &transerr); + const int trans = (int)tv_get_number_chk(&argvars[2], &transerr); int id = 0; if (!transerr && lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count @@ -9550,7 +9546,7 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "synIDtrans(id)" function static void f_synIDtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int id = tv_get_number(&argvars[0]); + int id = (int)tv_get_number(&argvars[0]); if (id > 0) { id = syn_get_final_id(id); @@ -9877,10 +9873,10 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) const bool overlapped = false; const bool detach = false; ChannelStdinMode stdin_mode = kChannelStdinPipe; - uint16_t term_width = MAX(0, curwin->w_width_inner - win_col_off(curwin)); + uint16_t term_width = (uint16_t)MAX(0, curwin->w_width_inner - win_col_off(curwin)); Channel *chan = channel_job_start(argv, on_stdout, on_stderr, on_exit, pty, rpc, overlapped, detach, stdin_mode, - cwd, term_width, curwin->w_height_inner, + cwd, term_width, (uint16_t)curwin->w_height_inner, env, &rettv->vval.v_number); if (rettv->vval.v_number <= 0) { return; @@ -9914,7 +9910,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) Error err = ERROR_INIT; // deprecated: use 'channel' buffer option dict_set_var(curbuf->b_vars, cstr_as_string("terminal_job_id"), - INTEGER_OBJ(chan->id), false, false, &err); + INTEGER_OBJ((Integer)chan->id), false, false, &err); api_clear_error(&err); dict_set_var(curbuf->b_vars, cstr_as_string("terminal_job_pid"), INTEGER_OBJ(pid), false, false, &err); @@ -9955,8 +9951,8 @@ static void f_timer_pause(typval_T *argvars, typval_T *unused, FunPtr fptr) if (!timer->paused && paused) { time_watcher_stop(&timer->tw); } else if (timer->paused && !paused) { - time_watcher_start(&timer->tw, timer_due_cb, timer->timeout, - timer->timeout); + time_watcher_start(&timer->tw, timer_due_cb, (uint64_t)timer->timeout, + (uint64_t)timer->timeout); } timer->paused = paused; } @@ -9981,7 +9977,7 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr) } dictitem_T *const di = tv_dict_find(dict, S_LEN("repeat")); if (di != NULL) { - repeat = tv_get_number(&di->di_tv); + repeat = (int)tv_get_number(&di->di_tv); if (repeat == 0) { repeat = 1; } @@ -9992,8 +9988,7 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (!callback_from_typval(&callback, &argvars[1])) { return; } - rettv->vval.v_number = - timer_start(tv_get_number(&argvars[0]), repeat, &callback); + rettv->vval.v_number = (varnumber_T)timer_start(tv_get_number(&argvars[0]), repeat, &callback); } /// "timer_stop(timerid)" function @@ -10190,7 +10185,7 @@ static void f_trim(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } } - rettv->vval.v_string = (char *)vim_strnsave(head, tail - head); + rettv->vval.v_string = (char *)vim_strnsave(head, (size_t)(tail - head)); } /// "type(expr)" function @@ -10294,7 +10289,7 @@ static void f_visualmode(typval_T *argvars, typval_T *rettv, FunPtr fptr) char_u str[2]; rettv->v_type = VAR_STRING; - str[0] = curbuf->b_visual_mode_eval; + str[0] = (char_u)curbuf->b_visual_mode_eval; str[1] = NUL; rettv->vval.v_string = (char *)vim_strsave(str); @@ -10508,29 +10503,29 @@ static void f_winrestview(typval_T *argvars, typval_T *rettv, FunPtr fptr) } else { dictitem_T *di; if ((di = tv_dict_find(dict, S_LEN("lnum"))) != NULL) { - curwin->w_cursor.lnum = tv_get_number(&di->di_tv); + curwin->w_cursor.lnum = (linenr_T)tv_get_number(&di->di_tv); } if ((di = tv_dict_find(dict, S_LEN("col"))) != NULL) { - curwin->w_cursor.col = tv_get_number(&di->di_tv); + curwin->w_cursor.col = (colnr_T)tv_get_number(&di->di_tv); } if ((di = tv_dict_find(dict, S_LEN("coladd"))) != NULL) { - curwin->w_cursor.coladd = tv_get_number(&di->di_tv); + curwin->w_cursor.coladd = (colnr_T)tv_get_number(&di->di_tv); } if ((di = tv_dict_find(dict, S_LEN("curswant"))) != NULL) { - curwin->w_curswant = tv_get_number(&di->di_tv); + curwin->w_curswant = (colnr_T)tv_get_number(&di->di_tv); curwin->w_set_curswant = false; } if ((di = tv_dict_find(dict, S_LEN("topline"))) != NULL) { - set_topline(curwin, tv_get_number(&di->di_tv)); + set_topline(curwin, (linenr_T)tv_get_number(&di->di_tv)); } if ((di = tv_dict_find(dict, S_LEN("topfill"))) != NULL) { - curwin->w_topfill = tv_get_number(&di->di_tv); + curwin->w_topfill = (int)tv_get_number(&di->di_tv); } if ((di = tv_dict_find(dict, S_LEN("leftcol"))) != NULL) { - curwin->w_leftcol = tv_get_number(&di->di_tv); + curwin->w_leftcol = (colnr_T)tv_get_number(&di->di_tv); } if ((di = tv_dict_find(dict, S_LEN("skipcol"))) != NULL) { - curwin->w_skipcol = tv_get_number(&di->di_tv); + curwin->w_skipcol = (colnr_T)tv_get_number(&di->di_tv); } check_cursor(); diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 1ee8581e00..4c17fdae02 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -3823,6 +3823,7 @@ void redrawcmd(void) redrawing_cmdline = true; + sb_text_restart_cmdline(); msg_start(); redrawcmdprompt(); diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c index 3c74b4bd8d..b89ab19226 100644 --- a/src/nvim/indent_c.c +++ b/src/nvim/indent_c.c @@ -3569,7 +3569,7 @@ term_again: // Are we at the start of a cpp base class declaration or // constructor initialization? XXX n = 0; - if (curbuf->b_ind_cpp_baseclass != 0 && theline[0] != '{') { + if (curbuf->b_ind_cpp_baseclass != 0) { n = cin_is_cpp_baseclass(&cache_cpp_baseclass); l = get_cursor_line_ptr(); } diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c index 8ccda5c7cd..e209192c2f 100644 --- a/src/nvim/insexpand.c +++ b/src/nvim/insexpand.c @@ -3324,6 +3324,272 @@ static bool ins_compl_use_match(int c) return true; } +/// Get the pattern, column and length for normal completion (CTRL-N CTRL-P +/// completion) +/// Sets the global variables: compl_col, compl_length and compl_pattern. +/// Uses the global variables: compl_cont_status and ctrl_x_mode +static int get_normal_compl_info(char_u *line, int startcol, colnr_T curs_col) +{ + if ((compl_cont_status & CONT_SOL) || ctrl_x_mode_path_defines()) { + if (!(compl_cont_status & CONT_ADDING)) { + while (--startcol >= 0 && vim_isIDc(line[startcol])) {} + compl_col += ++startcol; + compl_length = curs_col - startcol; + } + if (p_ic) { + compl_pattern = str_foldcase(line + compl_col, compl_length, NULL, 0); + } else { + compl_pattern = vim_strnsave(line + compl_col, (size_t)compl_length); + } + } else if (compl_cont_status & CONT_ADDING) { + char_u *prefix = (char_u *)"\\<"; + + // we need up to 2 extra chars for the prefix + compl_pattern = xmalloc(quote_meta(NULL, line + compl_col, + compl_length) + 2); + if (!vim_iswordp(line + compl_col) + || (compl_col > 0 && (vim_iswordp(mb_prevptr(line, line + compl_col))))) { + prefix = (char_u *)""; + } + STRCPY(compl_pattern, prefix); + (void)quote_meta(compl_pattern + STRLEN(prefix), + line + compl_col, compl_length); + } else if (--startcol < 0 + || !vim_iswordp(mb_prevptr(line, line + startcol + 1))) { + // Match any word of at least two chars + compl_pattern = vim_strsave((char_u *)"\\<\\k\\k"); + compl_col += curs_col; + compl_length = 0; + } else { + // Search the point of change class of multibyte character + // or not a word single byte character backward. + startcol -= utf_head_off(line, line + startcol); + int base_class = mb_get_class(line + startcol); + while (--startcol >= 0) { + int head_off = utf_head_off(line, line + startcol); + if (base_class != mb_get_class(line + startcol - head_off)) { + break; + } + startcol -= head_off; + } + compl_col += ++startcol; + compl_length = (int)curs_col - startcol; + if (compl_length == 1) { + // Only match word with at least two chars -- webb + // there's no need to call quote_meta, + // xmalloc(7) is enough -- Acevedo + compl_pattern = xmalloc(7); + STRCPY(compl_pattern, "\\<"); + (void)quote_meta(compl_pattern + 2, line + compl_col, 1); + STRCAT(compl_pattern, "\\k"); + } else { + compl_pattern = xmalloc(quote_meta(NULL, line + compl_col, + compl_length) + 2); + STRCPY(compl_pattern, "\\<"); + (void)quote_meta(compl_pattern + 2, line + compl_col, + compl_length); + } + } + + return OK; +} + +/// Get the pattern, column and length for whole line completion or for the +/// complete() function. +/// Sets the global variables: compl_col, compl_length and compl_pattern. +static int get_wholeline_compl_info(char_u *line, colnr_T curs_col) +{ + compl_col = (colnr_T)getwhitecols(line); + compl_length = (int)curs_col - (int)compl_col; + if (compl_length < 0) { // cursor in indent: empty pattern + compl_length = 0; + } + if (p_ic) { + compl_pattern = str_foldcase(line + compl_col, compl_length, NULL, 0); + } else { + compl_pattern = vim_strnsave(line + compl_col, (size_t)compl_length); + } + + return OK; +} + +/// Get the pattern, column and length for filename completion. +/// Sets the global variables: compl_col, compl_length and compl_pattern. +static int get_filename_compl_info(char_u *line, int startcol, colnr_T curs_col) +{ + // Go back to just before the first filename character. + if (startcol > 0) { + char_u *p = line + startcol; + + MB_PTR_BACK(line, p); + while (p > line && vim_isfilec(utf_ptr2char((char *)p))) { + MB_PTR_BACK(line, p); + } + if (p == line && vim_isfilec(utf_ptr2char((char *)p))) { + startcol = 0; + } else { + startcol = (int)(p - line) + 1; + } + } + + compl_col += startcol; + compl_length = (int)curs_col - startcol; + compl_pattern = addstar(line + compl_col, (size_t)compl_length, EXPAND_FILES); + + return OK; +} + +/// Get the pattern, column and length for command-line completion. +/// Sets the global variables: compl_col, compl_length and compl_pattern. +static int get_cmdline_compl_info(char_u *line, colnr_T curs_col) +{ + compl_pattern = vim_strnsave(line, (size_t)curs_col); + set_cmd_context(&compl_xp, compl_pattern, + (int)STRLEN(compl_pattern), curs_col, false); + if (compl_xp.xp_context == EXPAND_UNSUCCESSFUL + || compl_xp.xp_context == EXPAND_NOTHING) { + // No completion possible, use an empty pattern to get a + // "pattern not found" message. + compl_col = curs_col; + } else { + compl_col = (int)((char_u *)compl_xp.xp_pattern - compl_pattern); + } + compl_length = curs_col - compl_col; + + return OK; +} + +/// Get the pattern, column and length for user defined completion ('omnifunc', +/// 'completefunc' and 'thesaurusfunc') +/// Sets the global variables: compl_col, compl_length and compl_pattern. +/// Uses the global variable: spell_bad_len +static int get_userdefined_compl_info(colnr_T curs_col) +{ + // Call user defined function 'completefunc' with "a:findstart" + // set to 1 to obtain the length of text to use for completion. + const int save_State = State; + + // Call 'completefunc' or 'omnifunc' and get pattern length as a string + char_u *funcname = get_complete_funcname(ctrl_x_mode); + if (*funcname == NUL) { + semsg(_(e_notset), ctrl_x_mode_function() ? "completefunc" : "omnifunc"); + return FAIL; + } + + typval_T args[3]; + args[0].v_type = VAR_NUMBER; + args[1].v_type = VAR_STRING; + args[2].v_type = VAR_UNKNOWN; + args[0].vval.v_number = 1; + args[1].vval.v_string = ""; + + pos_T pos = curwin->w_cursor; + textlock++; + colnr_T col = (colnr_T)call_func_retnr((char *)funcname, 2, args); + textlock--; + + State = save_State; + curwin->w_cursor = pos; // restore the cursor position + validate_cursor(); + if (!equalpos(curwin->w_cursor, pos)) { + emsg(_(e_compldel)); + return FAIL; + } + + // Return value -2 means the user complete function wants to cancel the + // complete without an error, do the same if the function did not execute + // successfully. + if (col == -2 || aborting()) { + return FAIL; + } + // Return value -3 does the same as -2 and leaves CTRL-X mode. + if (col == -3) { + ctrl_x_mode = CTRL_X_NORMAL; + edit_submode = NULL; + if (!shortmess(SHM_COMPLETIONMENU)) { + msg_clr_cmdline(); + } + return FAIL; + } + + // Reset extended parameters of completion, when start new + // completion. + compl_opt_refresh_always = false; + + if (col < 0) { + col = curs_col; + } + compl_col = col; + if (compl_col > curs_col) { + compl_col = curs_col; + } + + // Setup variables for completion. Need to obtain "line" again, + // it may have become invalid. + char_u *line = ml_get(curwin->w_cursor.lnum); + compl_length = curs_col - compl_col; + compl_pattern = vim_strnsave(line + compl_col, (size_t)compl_length); + + return OK; +} + +/// Get the pattern, column and length for spell completion. +/// Sets the global variables: compl_col, compl_length and compl_pattern. +/// Uses the global variable: spell_bad_len +static int get_spell_compl_info(int startcol, colnr_T curs_col) +{ + if (spell_bad_len > 0) { + assert(spell_bad_len <= INT_MAX); + compl_col = curs_col - (int)spell_bad_len; + } else { + compl_col = spell_word_start(startcol); + } + if (compl_col >= (colnr_T)startcol) { + compl_length = 0; + compl_col = curs_col; + } else { + spell_expand_check_cap(compl_col); + compl_length = (int)curs_col - compl_col; + } + // Need to obtain "line" again, it may have become invalid. + char_u *line = ml_get(curwin->w_cursor.lnum); + compl_pattern = vim_strnsave(line + compl_col, (size_t)compl_length); + + return OK; +} + +/// Get the completion pattern, column and length. +static int compl_get_info(char_u *line, int startcol, colnr_T curs_col, bool *line_invalid) +{ + if (ctrl_x_mode_normal() + || ((ctrl_x_mode & CTRL_X_WANT_IDENT) + && !thesaurus_func_complete(ctrl_x_mode))) { + return get_normal_compl_info(line, startcol, curs_col); + } else if (ctrl_x_mode_line_or_eval()) { + return get_wholeline_compl_info(line, curs_col); + } else if (ctrl_x_mode_files()) { + return get_filename_compl_info(line, startcol, curs_col); + } else if (ctrl_x_mode == CTRL_X_CMDLINE) { + return get_cmdline_compl_info(line, curs_col); + } else if (ctrl_x_mode_function() || ctrl_x_mode_omni() + || thesaurus_func_complete(ctrl_x_mode)) { + if (get_userdefined_compl_info(curs_col) == FAIL) { + return FAIL; + } + *line_invalid = true; // 'line' may have become invalid + } else if (ctrl_x_mode_spell()) { + if (get_spell_compl_info(startcol, curs_col) == FAIL) { + return FAIL; + } + *line_invalid = true; // 'line' may have become invalid + } else { + internal_error("ins_complete()"); + return FAIL; + } + + return OK; +} + /// Do Insert mode completion. /// Called when character "c" was typed, which has a meaning for completion. /// Returns OK if completion was done, FAIL if something failed. @@ -3338,6 +3604,7 @@ int ins_complete(int c, bool enable_pum) int insert_match; const bool save_did_ai = did_ai; int flags = CP_ORIGINAL_TEXT; + bool line_invalid = false; compl_direction = ins_compl_key2dir(c); insert_match = ins_compl_use_match(c); @@ -3427,208 +3694,23 @@ int ins_complete(int c, bool enable_pum) } // Work out completion pattern and original text -- webb - if (ctrl_x_mode_normal() - || (ctrl_x_mode & CTRL_X_WANT_IDENT - && !thesaurus_func_complete(ctrl_x_mode))) { - if ((compl_cont_status & CONT_SOL) || ctrl_x_mode_path_defines()) { - if (!(compl_cont_status & CONT_ADDING)) { - while (--startcol >= 0 && vim_isIDc(line[startcol])) {} - compl_col += ++startcol; - compl_length = curs_col - startcol; - } - if (p_ic) { - compl_pattern = str_foldcase(line + compl_col, compl_length, NULL, 0); - } else { - compl_pattern = vim_strnsave(line + compl_col, (size_t)compl_length); - } - } else if (compl_cont_status & CONT_ADDING) { - char_u *prefix = (char_u *)"\\<"; - - // we need up to 2 extra chars for the prefix - compl_pattern = xmalloc(quote_meta(NULL, line + compl_col, - compl_length) + 2); - if (!vim_iswordp(line + compl_col) - || (compl_col > 0 && (vim_iswordp(mb_prevptr(line, line + compl_col))))) { - prefix = (char_u *)""; - } - STRCPY(compl_pattern, prefix); - (void)quote_meta(compl_pattern + STRLEN(prefix), - line + compl_col, compl_length); - } else if (--startcol < 0 - || !vim_iswordp(mb_prevptr(line, line + startcol + 1))) { - // Match any word of at least two chars - compl_pattern = vim_strsave((char_u *)"\\<\\k\\k"); - compl_col += curs_col; - compl_length = 0; - } else { - // Search the point of change class of multibyte character - // or not a word single byte character backward. - startcol -= utf_head_off(line, line + startcol); - int base_class = mb_get_class(line + startcol); - while (--startcol >= 0) { - int head_off = utf_head_off(line, line + startcol); - if (base_class != mb_get_class(line + startcol - head_off)) { - break; - } - startcol -= head_off; - } - compl_col += ++startcol; - compl_length = (int)curs_col - startcol; - if (compl_length == 1) { - // Only match word with at least two chars -- webb - // there's no need to call quote_meta, - // xmalloc(7) is enough -- Acevedo - compl_pattern = xmalloc(7); - STRCPY(compl_pattern, "\\<"); - (void)quote_meta(compl_pattern + 2, line + compl_col, 1); - STRCAT(compl_pattern, "\\k"); - } else { - compl_pattern = xmalloc(quote_meta(NULL, line + compl_col, - compl_length) + 2); - STRCPY(compl_pattern, "\\<"); - (void)quote_meta(compl_pattern + 2, line + compl_col, - compl_length); - } - } - } else if (ctrl_x_mode_line_or_eval()) { - compl_col = (colnr_T)getwhitecols(line); - compl_length = (int)curs_col - (int)compl_col; - if (compl_length < 0) { // cursor in indent: empty pattern - compl_length = 0; - } - if (p_ic) { - compl_pattern = str_foldcase(line + compl_col, compl_length, NULL, 0); - } else { - compl_pattern = vim_strnsave(line + compl_col, (size_t)compl_length); - } - } else if (ctrl_x_mode_files()) { - // Go back to just before the first filename character. - if (startcol > 0) { - char_u *p = line + startcol; - - MB_PTR_BACK(line, p); - while (p > line && vim_isfilec(utf_ptr2char((char *)p))) { - MB_PTR_BACK(line, p); - } - if (p == line && vim_isfilec(utf_ptr2char((char *)p))) { - startcol = 0; - } else { - startcol = (int)(p - line) + 1; - } - } - - compl_col += startcol; - compl_length = (int)curs_col - startcol; - compl_pattern = addstar(line + compl_col, (size_t)compl_length, EXPAND_FILES); - } else if (ctrl_x_mode == CTRL_X_CMDLINE) { - compl_pattern = vim_strnsave(line, (size_t)curs_col); - set_cmd_context(&compl_xp, compl_pattern, - (int)STRLEN(compl_pattern), curs_col, false); - if (compl_xp.xp_context == EXPAND_UNSUCCESSFUL - || compl_xp.xp_context == EXPAND_NOTHING) { - // No completion possible, use an empty pattern to get a - // "pattern not found" message. - compl_col = curs_col; - } else { - compl_col = (int)((char_u *)compl_xp.xp_pattern - compl_pattern); - } - compl_length = curs_col - compl_col; - } else if (ctrl_x_mode_function() || ctrl_x_mode_omni() - || thesaurus_func_complete(ctrl_x_mode)) { - // Call user defined function 'completefunc' with "a:findstart" - // set to 1 to obtain the length of text to use for completion. - char_u *funcname; - pos_T pos; - const int save_State = State; - - // Call 'completefunc' or 'omnifunc' and get pattern length as a string - funcname = get_complete_funcname(ctrl_x_mode); - if (*funcname == NUL) { - semsg(_(e_notset), ctrl_x_mode_function() ? "completefunc" : "omnifunc"); + if (compl_get_info(line, startcol, curs_col, &line_invalid) == FAIL) { + if (ctrl_x_mode_function() || ctrl_x_mode_omni() + || thesaurus_func_complete(ctrl_x_mode)) { // restore did_ai, so that adding comment leader works did_ai = save_did_ai; - return FAIL; } - - typval_T args[3]; - args[0].v_type = VAR_NUMBER; - args[1].v_type = VAR_STRING; - args[2].v_type = VAR_UNKNOWN; - args[0].vval.v_number = 1; - args[1].vval.v_string = ""; - - pos = curwin->w_cursor; - textlock++; - colnr_T col = (colnr_T)call_func_retnr((char *)funcname, 2, args); - textlock--; - - State = save_State; - curwin->w_cursor = pos; // restore the cursor position - validate_cursor(); - if (!equalpos(curwin->w_cursor, pos)) { - emsg(_(e_compldel)); - return FAIL; - } - - // Return value -2 means the user complete function wants to cancel the - // complete without an error, do the same if the function did not execute - // successfully. - if (col == -2 || aborting()) { - return FAIL; - } - // Return value -3 does the same as -2 and leaves CTRL-X mode. - if (col == -3) { - ctrl_x_mode = CTRL_X_NORMAL; - edit_submode = NULL; - if (!shortmess(SHM_COMPLETIONMENU)) { - msg_clr_cmdline(); - } - return FAIL; - } - - // Reset extended parameters of completion, when start new - // completion. - compl_opt_refresh_always = false; - - if (col < 0) { - col = curs_col; - } - compl_col = col; - if (compl_col > curs_col) { - compl_col = curs_col; - } - - // Setup variables for completion. Need to obtain "line" again, - // it may have become invalid. - line = ml_get(curwin->w_cursor.lnum); - compl_length = curs_col - compl_col; - compl_pattern = vim_strnsave(line + compl_col, (size_t)compl_length); - } else if (ctrl_x_mode_spell()) { - if (spell_bad_len > 0) { - assert(spell_bad_len <= INT_MAX); - compl_col = curs_col - (int)spell_bad_len; - } else { - compl_col = spell_word_start(startcol); - } - if (compl_col >= (colnr_T)startcol) { - compl_length = 0; - compl_col = curs_col; - } else { - spell_expand_check_cap(compl_col); - compl_length = (int)curs_col - compl_col; - } - // Need to obtain "line" again, it may have become invalid. - line = ml_get(curwin->w_cursor.lnum); - compl_pattern = vim_strnsave(line + compl_col, (size_t)compl_length); - } else { - internal_error("ins_complete()"); return FAIL; } + // If "line" was changed while getting completion info get it again. + if (line_invalid) { + line = ml_get(curwin->w_cursor.lnum); + } if (compl_cont_status & CONT_ADDING) { edit_submode_pre = (char_u *)_(" Adding"); if (ctrl_x_mode_line_or_eval()) { - // Insert a new line, keep indentation but ignore 'comments' + // Insert a new line, keep indentation but ignore 'comments'. char_u *old = curbuf->b_p_com; curbuf->b_p_com = (char_u *)""; diff --git a/src/nvim/message.c b/src/nvim/message.c index 3a6c690ff6..80d11c096b 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -2503,6 +2503,7 @@ static void store_sb_text(char_u **sb_str, char_u *s, int attr, int *sb_col, int if (do_clear_sb_text == SB_CLEAR_ALL || do_clear_sb_text == SB_CLEAR_CMDLINE_DONE) { clear_sb_text(do_clear_sb_text == SB_CLEAR_ALL); + msg_sb_eol(); // prevent messages from overlapping do_clear_sb_text = SB_CLEAR_NONE; } @@ -2537,18 +2538,47 @@ void may_clear_sb_text(void) do_clear_sb_text = SB_CLEAR_ALL; } -/// Starting to edit the command line, do not clear messages now. +/// Starting to edit the command line: do not clear messages now. void sb_text_start_cmdline(void) { + if (do_clear_sb_text == SB_CLEAR_CMDLINE_BUSY) { + // Invoking command line recursively: the previous-level command line + // doesn't need to be remembered as it will be redrawn when returning + // to that level. + sb_text_restart_cmdline(); + } else { + msg_sb_eol(); + do_clear_sb_text = SB_CLEAR_CMDLINE_BUSY; + } +} + +/// Redrawing the command line: clear the last unfinished line. +void sb_text_restart_cmdline(void) +{ + // Needed when returning from nested command line. do_clear_sb_text = SB_CLEAR_CMDLINE_BUSY; - msg_sb_eol(); + + if (last_msgchunk == NULL || last_msgchunk->sb_eol) { + // No unfinished line: don't clear anything. + return; + } + + msgchunk_T *tofree = msg_sb_start(last_msgchunk); + last_msgchunk = tofree->sb_prev; + if (last_msgchunk != NULL) { + last_msgchunk->sb_next = NULL; + } + while (tofree != NULL) { + msgchunk_T *tofree_next = tofree->sb_next; + xfree(tofree); + tofree = tofree_next; + } } -/// Ending to edit the command line. Clear old lines but the last one later. +/// Ending to edit the command line: clear old lines but the last one later. void sb_text_end_cmdline(void) { do_clear_sb_text = SB_CLEAR_CMDLINE_DONE; - msg_sb_eol(); } /// Clear any text remembered for scrolling back. diff --git a/src/nvim/option.c b/src/nvim/option.c index 7edc2e55f5..0feeae84e4 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1327,7 +1327,6 @@ int do_set(char *arg, int opt_flags) char *saved_newval = NULL; unsigned newlen; int comma; - bool new_value_alloced = false; // new string option was allocated // When using ":set opt=val" for a global option // with a local value the local value will be @@ -1367,7 +1366,6 @@ int do_set(char *arg, int opt_flags) // default value was already expanded, only // required when an environment variable was set // later - new_value_alloced = true; if (newval == NULL) { newval = empty_option; } else if (!(options[opt_idx].flags & P_NO_DEF_EXP)) { @@ -1381,7 +1379,6 @@ int do_set(char *arg, int opt_flags) } } else if (nextchar == '<') { // set to global val newval = vim_strsave(*(char_u **)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL)); - new_value_alloced = true; } else { arg++; // jump to after the '=' or ':' @@ -1626,7 +1623,6 @@ int do_set(char *arg, int opt_flags) if (save_arg != NULL) { // number for 'whichwrap' arg = (char *)save_arg; } - new_value_alloced = true; } // Set the new value. @@ -1661,8 +1657,7 @@ int do_set(char *arg, int opt_flags) // for ":set" on local options. Note: when setting // 'syntax' or 'filetype' autocommands may be // triggered that can cause havoc. - errmsg = did_set_string_option(opt_idx, (char_u **)varp, - new_value_alloced, oldval, + errmsg = did_set_string_option(opt_idx, (char_u **)varp, oldval, errbuf, sizeof(errbuf), opt_flags, &value_checked); @@ -2301,9 +2296,9 @@ static char *set_string_option(const int opt_idx, const char *const value, const char *const saved_newval = xstrdup(s); int value_checked = false; - char *const r = did_set_string_option(opt_idx, (char_u **)varp, true, - (char_u *)oldval, - NULL, 0, opt_flags, &value_checked); + char *const r = did_set_string_option(opt_idx, (char_u **)varp, (char_u *)oldval, + NULL, 0, + opt_flags, &value_checked); if (r == NULL) { did_set_option(opt_idx, opt_flags, true, value_checked); } @@ -2432,19 +2427,18 @@ static char *check_mousescroll(char *string) } /// Handle string options that need some action to perform when changed. +/// The new value must be allocated. /// Returns NULL for success, or an error message for an error. /// /// @param opt_idx index in options[] table /// @param varp pointer to the option variable -/// @param new_value_alloced new value was allocated /// @param oldval previous value of the option /// @param errbuf buffer for errors, or NULL /// @param errbuflen length of errors buffer /// @param opt_flags OPT_LOCAL and/or OPT_GLOBAL /// @param value_checked value was checked to be safe, no need to set P_INSECURE -static char *did_set_string_option(int opt_idx, char_u **varp, bool new_value_alloced, - char_u *oldval, char *errbuf, size_t errbuflen, int opt_flags, - int *value_checked) +static char *did_set_string_option(int opt_idx, char_u **varp, char_u *oldval, char *errbuf, + size_t errbuflen, int opt_flags, int *value_checked) { char *errmsg = NULL; char_u *s, *p; @@ -3099,11 +3093,8 @@ ambw_end: (char **)&p, REPTERM_FROM_PART | REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS); if (p != NULL) { - if (new_value_alloced) { - free_string_option(p_pt); - } + free_string_option(p_pt); p_pt = p; - new_value_alloced = true; } } } else if (varp == &p_bs) { // 'backspace' @@ -3346,9 +3337,7 @@ ambw_end: * If error detected, restore the previous value. */ if (errmsg != NULL) { - if (new_value_alloced) { - free_string_option(*varp); - } + free_string_option(*varp); *varp = oldval; /* * When resetting some values, need to act on it. @@ -3365,11 +3354,7 @@ ambw_end: if (free_oldval) { free_string_option(oldval); } - if (new_value_alloced) { - options[opt_idx].flags |= P_ALLOCED; - } else { - options[opt_idx].flags &= ~P_ALLOCED; - } + options[opt_idx].flags |= P_ALLOCED; if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 && ((int)options[opt_idx].indir & PV_BOTH)) { diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 2138437b29..d5797e87e5 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -3147,13 +3147,31 @@ static void qf_list_entry(qfline_T *qfp, int qf_idx, bool cursel) } msg_puts(" "); + char_u *tbuf = IObuff; + size_t tbuflen = IOSIZE; + size_t len = STRLEN(qfp->qf_text) + 3; + + if (len > IOSIZE) { + tbuf = xmalloc(len); + if (tbuf != NULL) { + tbuflen = len; + } else { + tbuf = IObuff; + } + } + // Remove newlines and leading whitespace from the text. For an // unrecognized line keep the indent, the compiler may mark a word - // with ^^^^. */ + // with ^^^^. qf_fmt_text((fname != NULL || qfp->qf_lnum != 0) ? skipwhite(qfp->qf_text) : qfp->qf_text, - (char *)IObuff, IOSIZE); - msg_prt_line(IObuff, false); + (char *)tbuf, (int)tbuflen); + msg_prt_line(tbuf, false); + + if (tbuf != IObuff) { + xfree(tbuf); + } + ui_flush(); // show one line at a time } diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index 9d2fd2637d..7fb3c90eee 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -903,8 +903,8 @@ void suggest_load_files(void) } // <SUGHEADER>: <fileID> <versionnr> <timestamp> - for (i = 0; i < VIMSUGMAGICL; ++i) { - buf[i] = getc(fd); // <fileID> + for (i = 0; i < VIMSUGMAGICL; i++) { + buf[i] = (char_u)getc(fd); // <fileID> } if (STRNCMP(buf, VIMSUGMAGIC, VIMSUGMAGICL) != 0) { semsg(_("E778: This does not look like a .sug file: %s"), @@ -965,7 +965,7 @@ someerror: if (c < 0) { goto someerror; } - GA_APPEND(char_u, &ga, c); + GA_APPEND(char_u, &ga, (char_u)c); if (c == NUL) { break; } @@ -1009,7 +1009,7 @@ static char_u *read_cnt_string(FILE *fd, int cnt_bytes, int *cntp) *cntp = SP_TRUNCERROR; return NULL; } - cnt = (cnt << 8) + (unsigned)c; + cnt = (int)(((unsigned)cnt << 8) + (unsigned)c); } *cntp = cnt; if (cnt == 0) { @@ -1081,7 +1081,7 @@ static int read_prefcond_section(FILE *fd, slang_T *lp) return SP_FORMERROR; } - lp->sl_prefprog = xcalloc(cnt, sizeof(regprog_T *)); + lp->sl_prefprog = xcalloc((size_t)cnt, sizeof(regprog_T *)); lp->sl_prefixcnt = cnt; for (int i = 0; i < cnt; i++) { @@ -1146,7 +1146,7 @@ static int read_rep_section(FILE *fd, garray_T *gap, int16_t *first) for (int i = 0; i < gap->ga_len; ++i) { ftp = &((fromto_T *)gap->ga_data)[i]; if (first[*ftp->ft_from] == -1) { - first[*ftp->ft_from] = i; + first[*ftp->ft_from] = (int16_t)i; } } return 0; @@ -1193,7 +1193,7 @@ static int read_sal_section(FILE *fd, slang_T *slang) if (ccnt < 0) { return SP_TRUNCERROR; } - p = xmalloc(ccnt + 2); + p = xmalloc((size_t)ccnt + 2); smp->sm_lead = p; // Read up to the first special char into sm_lead. @@ -1203,7 +1203,7 @@ static int read_sal_section(FILE *fd, slang_T *slang) if (vim_strchr("0123456789(-<^$", c) != NULL) { break; } - *p++ = c; + *p++ = (char_u)c; } smp->sm_leadlen = (int)(p - smp->sm_lead); *p++ = NUL; @@ -1216,7 +1216,7 @@ static int read_sal_section(FILE *fd, slang_T *slang) if (c == ')') { break; } - *p++ = c; + *p++ = (char_u)c; } *p++ = NUL; if (++i < ccnt) { @@ -1230,7 +1230,7 @@ static int read_sal_section(FILE *fd, slang_T *slang) smp->sm_rules = p; if (i < ccnt) { // store the char we got while checking for end of sm_lead - *p++ = c; + *p++ = (char_u)c; } i++; if (i < ccnt) { @@ -1302,7 +1302,7 @@ static int read_words_section(FILE *fd, slang_T *lp, int len) if (c == EOF) { return SP_TRUNCERROR; } - word[i] = c; + word[i] = (char_u)c; if (word[i] == NUL) { break; } @@ -1363,11 +1363,6 @@ static int read_compound(FILE *fd, slang_T *slang, int len) int todo = len; int c; int atstart; - char_u *pat; - char_u *pp; - char_u *cp; - char_u *ap; - char_u *crp; int cnt; garray_T *gap; @@ -1432,25 +1427,25 @@ static int read_compound(FILE *fd, slang_T *slang, int len) // Conversion to utf-8 may double the size. c = todo * 2 + 7; c += todo * 2; - pat = xmalloc(c); + char_u *pat = xmalloc((size_t)c); // We also need a list of all flags that can appear at the start and one // for all flags. - cp = xmalloc(todo + 1); + char_u *cp = xmalloc((size_t)todo + 1); slang->sl_compstartflags = cp; *cp = NUL; - ap = xmalloc(todo + 1); + char_u *ap = xmalloc((size_t)todo + 1); slang->sl_compallflags = ap; *ap = NUL; // And a list of all patterns in their original form, for checking whether // compounding may work in match_compoundrule(). This is freed when we // encounter a wildcard, the check doesn't work then. - crp = xmalloc(todo + 1); + char_u *crp = xmalloc((size_t)todo + 1); slang->sl_comprules = crp; - pp = pat; + char_u *pp = pat; *pp++ = '^'; *pp++ = '\\'; *pp++ = '('; @@ -1466,7 +1461,7 @@ static int read_compound(FILE *fd, slang_T *slang, int len) // Add all flags to "sl_compallflags". if (vim_strchr("?*+[]/", c) == NULL && !byte_in_str(slang->sl_compallflags, c)) { - *ap++ = c; + *ap++ = (char_u)c; *ap = NUL; } @@ -1479,7 +1474,7 @@ static int read_compound(FILE *fd, slang_T *slang, int len) atstart = 0; } else { if (!byte_in_str(slang->sl_compstartflags, c)) { - *cp++ = c; + *cp++ = (char_u)c; *cp = NUL; } if (atstart == 1) { @@ -1494,7 +1489,7 @@ static int read_compound(FILE *fd, slang_T *slang, int len) XFREE_CLEAR(slang->sl_comprules); crp = NULL; } else { - *crp++ = c; + *crp++ = (char_u)c; } } @@ -1561,7 +1556,7 @@ static int set_sofo(slang_T *lp, char_u *from, char_u *to) // Allocate the lists. for (int i = 0; i < 256; i++) { if (lp->sl_sal_first[i] > 0) { - p = xmalloc(sizeof(int) * (lp->sl_sal_first[i] * 2 + 1)); + p = xmalloc(sizeof(int) * (size_t)(lp->sl_sal_first[i] * 2 + 1)); ((int **)gap->ga_data)[i] = (int *)p; *(int *)p = 0; } @@ -1631,7 +1626,7 @@ static void set_sal_first(slang_T *lp) i++; n--; tsal = smp[i + n]; - memmove(smp + i + 1, smp + i, sizeof(salitem_T) * n); + memmove(smp + i + 1, smp + i, sizeof(salitem_T) * (size_t)n); smp[i] = tsal; } } @@ -1645,7 +1640,7 @@ static int *mb_str2wide(char_u *s) { int i = 0; - int *res = xmalloc((mb_charlen(s) + 1) * sizeof(int)); + int *res = xmalloc(((size_t)mb_charlen(s) + 1) * sizeof(int)); for (char_u *p = s; *p != NUL;) { res[i++] = mb_ptr2char_adv((const char_u **)&p); } @@ -1682,18 +1677,18 @@ static int spell_read_tree(FILE *fd, char_u **bytsp, long *bytsp_len, idx_T **id } if (len > 0) { // Allocate the byte array. - bp = xmalloc(len); + bp = xmalloc((size_t)len); *bytsp = bp; if (bytsp_len != NULL) { *bytsp_len = len; } // Allocate the index array. - ip = xcalloc(len, sizeof(*ip)); + ip = xcalloc((size_t)len, sizeof(*ip)); *idxsp = ip; // Recursively read the tree and store it in the array. - idx = read_tree_node(fd, bp, ip, len, 0, prefixtree, prefixcnt); + idx = read_tree_node(fd, bp, ip, (int)len, 0, prefixtree, prefixcnt); if (idx < 0) { return idx; } @@ -1733,7 +1728,7 @@ static idx_T read_tree_node(FILE *fd, char_u *byts, idx_T *idxs, int maxidx, idx if (startidx + len >= maxidx) { return SP_FORMERROR; } - byts[idx++] = len; + byts[idx++] = (char_u)len; // Read the byte values, flag/region bytes and shared indexes. for (i = 1; i <= len; ++i) { @@ -1793,7 +1788,7 @@ static idx_T read_tree_node(FILE *fd, char_u *byts, idx_T *idxs, int maxidx, idx c = getc(fd); // <xbyte> } } - byts[idx++] = c; + byts[idx++] = (char_u)c; } // Recursively read the children for non-shared siblings. @@ -2257,7 +2252,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname) if (compflags != NULL) { l += (int)STRLEN(compflags) + 1; } - p = getroom(spin, l, false); + p = getroom(spin, (size_t)l, false); if (compflags != NULL) { STRCPY(p, compflags); STRCAT(p, "/"); @@ -2885,7 +2880,7 @@ static unsigned get_affitem(int flagtype, char_u **pp) res = mb_ptr2char_adv((const char_u **)pp) + (res << 16); } } - return res; + return (unsigned)res; } // Process the "compflags" string used in an affix file and append it to @@ -2911,7 +2906,7 @@ static void process_compflags(spellinfo_T *spin, afffile_T *aff, char_u *compfla if (spin->si_compflags != NULL) { len += (int)STRLEN(spin->si_compflags) + 1; } - p = getroom(spin, len, false); + p = getroom(spin, (size_t)len, false); if (spin->si_compflags != NULL) { STRCPY(p, spin->si_compflags); STRCAT(p, "/"); @@ -2947,7 +2942,7 @@ static void process_compflags(spellinfo_T *spin, afffile_T *aff, char_u *compfla ci->ci_newID = id; hash_add(&aff->af_comp, ci->ci_key); } - *tp++ = id; + *tp++ = (char_u)id; } if (aff->af_flagtype == AFT_NUM && *p == ',') { ++p; @@ -2978,15 +2973,15 @@ static bool flag_in_afflist(int flagtype, char_u *afflist, unsigned flag) switch (flagtype) { case AFT_CHAR: - return vim_strchr((char *)afflist, flag) != NULL; + return vim_strchr((char *)afflist, (int)flag) != NULL; case AFT_CAPLONG: case AFT_LONG: for (p = afflist; *p != NUL;) { - n = mb_ptr2char_adv((const char_u **)&p); + n = (unsigned)mb_ptr2char_adv((const char_u **)&p); if ((flagtype == AFT_LONG || (n >= 'A' && n <= 'Z')) && *p != NUL) { - n = mb_ptr2char_adv((const char_u **)&p) + (n << 16); + n = (unsigned)mb_ptr2char_adv((const char_u **)&p) + (n << 16); } if (n == flag) { return true; @@ -3362,7 +3357,7 @@ static int get_pfxlist(afffile_T *affile, char_u *afflist, char_u *store_afflist if (!HASHITEM_EMPTY(hi)) { id = HI2AH(hi)->ah_newID; if (id != 0) { - store_afflist[cnt++] = id; + store_afflist[cnt++] = (char_u)id; } } } @@ -3393,7 +3388,7 @@ static void get_compflags(afffile_T *affile, char_u *afflist, char_u *store_affl STRLCPY(key, prevp, p - prevp + 1); hi = hash_find(&affile->af_comp, (char *)key); if (!HASHITEM_EMPTY(hi)) { - store_afflist[cnt++] = HI2CI(hi)->ci_newID; + store_afflist[cnt++] = (char_u)HI2CI(hi)->ci_newID; } } if (affile->af_flagtype == AFT_NUM && *p == ',') { @@ -3856,11 +3851,10 @@ static void *getroom(spellinfo_T *spin, size_t len, bool align) if (align && bl != NULL) { // Round size up for alignment. On some systems structures need to be // aligned to the size of a pointer (e.g., SPARC). - bl->sb_used = (bl->sb_used + sizeof(char *) - 1) - & ~(sizeof(char *) - 1); + bl->sb_used = (int)(((size_t)bl->sb_used + sizeof(char *) - 1) & ~(sizeof(char *) - 1)); } - if (bl == NULL || bl->sb_used + len > SBLOCKSIZE) { + if (bl == NULL || (size_t)bl->sb_used + len > SBLOCKSIZE) { // Allocate a block of memory. It is not freed until much later. bl = xcalloc(1, (sizeof(sblock_T) + SBLOCKSIZE)); bl->sb_next = spin->si_blocks; @@ -4072,9 +4066,9 @@ static int tree_add_word(spellinfo_T *spin, char_u *word, wordnode_T *root, int } if (word[i] == NUL) { - node->wn_flags = flags; - node->wn_region |= region; - node->wn_affixID = affixID; + node->wn_flags = (uint16_t)flags; + node->wn_region |= (int16_t)region; + node->wn_affixID = (char_u)affixID; break; } prev = &node->wn_child; @@ -4298,12 +4292,12 @@ static long node_compress(spellinfo_T *spin, wordnode_T *node, hashtab_T *ht, lo // Make a hash key for the node and its siblings, so that we can quickly // find a lookalike node. This must be done after compressing the sibling // list, otherwise the hash key would become invalid by the compression. - node->wn_u1.hashkey[0] = len; + node->wn_u1.hashkey[0] = (char_u)len; nr = 0; for (np = node; np != NULL; np = np->wn_sibling) { if (np->wn_byte == NUL) { // end node: use wn_flags, wn_region and wn_affixID - n = np->wn_flags + (np->wn_region << 8) + (np->wn_affixID << 16); + n = (unsigned)(np->wn_flags + (np->wn_region << 8) + (np->wn_affixID << 16)); } else { // byte node: use the byte value and the child pointer n = (unsigned)(np->wn_byte + ((uintptr_t)np->wn_child << 8)); @@ -4313,13 +4307,13 @@ static long node_compress(spellinfo_T *spin, wordnode_T *node, hashtab_T *ht, lo // Avoid NUL bytes, it terminates the hash key. n = nr & 0xff; - node->wn_u1.hashkey[1] = n == 0 ? 1 : n; + node->wn_u1.hashkey[1] = n == 0 ? 1 : (char_u)n; n = (nr >> 8) & 0xff; - node->wn_u1.hashkey[2] = n == 0 ? 1 : n; + node->wn_u1.hashkey[2] = n == 0 ? 1 : (char_u)n; n = (nr >> 16) & 0xff; - node->wn_u1.hashkey[3] = n == 0 ? 1 : n; + node->wn_u1.hashkey[3] = n == 0 ? 1 : (char_u)n; n = (nr >> 24) & 0xff; - node->wn_u1.hashkey[4] = n == 0 ? 1 : n; + node->wn_u1.hashkey[4] = n == 0 ? 1 : (char_u)n; node->wn_u1.hashkey[5] = NUL; // Check for CTRL-C pressed now and then. @@ -5034,7 +5028,7 @@ static int sug_filltree(spellinfo_T *spin, slang_T *slang) // We use the "flags" field for the MSB of the wordnr, // "region" for the LSB of the wordnr. if (tree_add_word(spin, tsalword, spin->si_foldroot, - words_done >> 16, words_done & 0xffff, + (int)(words_done >> 16), words_done & 0xffff, 0) == FAIL) { return FAIL; } @@ -5054,7 +5048,7 @@ static int sug_filltree(spellinfo_T *spin, slang_T *slang) } } else { // Normal char, go one level deeper. - tword[depth++] = c; + tword[depth++] = (char_u)c; arridx[depth] = idxs[n]; curi[depth] = 1; wordcount[depth] = 0; @@ -5170,25 +5164,25 @@ static int offset2bytes(int nr, char_u *buf) b4 = rem / 255 + 1; if (b4 > 1 || b3 > 0x1f) { // 4 bytes - buf[0] = 0xe0 + b4; - buf[1] = b3; - buf[2] = b2; - buf[3] = b1; + buf[0] = (char_u)(0xe0 + b4); + buf[1] = (char_u)b3; + buf[2] = (char_u)b2; + buf[3] = (char_u)b1; return 4; } if (b3 > 1 || b2 > 0x3f) { // 3 bytes - buf[0] = 0xc0 + b3; - buf[1] = b2; - buf[2] = b1; + buf[0] = (char_u)(0xc0 + b3); + buf[1] = (char_u)b2; + buf[2] = (char_u)b1; return 3; } if (b2 > 1 || b1 > 0x7f) { // 2 bytes - buf[0] = 0x80 + b2; - buf[1] = b1; + buf[0] = (char_u)(0x80 + b2); + buf[1] = (char_u)b1; return 2; } // 1 byte - buf[0] = b1; + buf[0] = (char_u)b1; return 1; } @@ -5373,9 +5367,8 @@ static void mkspell(int fcount, char_u **fnames, bool ascii, bool over_write, bo semsg(_("E755: Invalid region in %s"), innames[i]); goto theend; } - spin.si_region_name[i * 2] = TOLOWER_ASC(innames[i][len - 2]); - spin.si_region_name[i * 2 + 1] = - TOLOWER_ASC(innames[i][len - 1]); + spin.si_region_name[i * 2] = (char_u)TOLOWER_ASC(innames[i][len - 2]); + spin.si_region_name[i * 2 + 1] = (char_u)TOLOWER_ASC(innames[i][len - 1]); } } spin.si_region_count = incount; @@ -5645,7 +5638,7 @@ void spell_add_word(char_u *word, int len, SpellAddType what, int idx, bool undo // the file again. *p = NUL; os_mkdir((char *)fname, 0755); - *p = c; + *p = (char_u)c; fd = os_fopen((char *)fname, "a"); } } @@ -5727,19 +5720,19 @@ static void init_spellfile(void) } else { // Create the "spell" directory if it doesn't exist yet. l = (int)STRLEN(buf); - vim_snprintf((char *)buf + l, MAXPATHL - l, "/spell"); + vim_snprintf((char *)buf + l, MAXPATHL - (size_t)l, "/spell"); if (os_file_is_writable((char *)buf) != 2) { os_mkdir((char *)buf, 0755); } l = (int)STRLEN(buf); - vim_snprintf((char *)buf + l, MAXPATHL - l, + vim_snprintf((char *)buf + l, MAXPATHL - (size_t)l, "/%.*s", (int)(lend - lstart), lstart); } l = (int)STRLEN(buf); fname = LANGP_ENTRY(curwin->w_s->b_langp, 0) ->lp_slang->sl_fname; - vim_snprintf((char *)buf + l, MAXPATHL - l, ".%s.add", + vim_snprintf((char *)buf + l, MAXPATHL - (size_t)l, ".%s.add", ((fname != NULL && strstr(path_tail((char *)fname), ".ascii.") != NULL) ? "ascii" @@ -5776,9 +5769,9 @@ static void set_spell_charflags(char_u *flags, int cnt, char_u *fol) if (*p != NUL) { c = mb_ptr2char_adv((const char_u **)&p); - new_st.st_fold[i + 128] = c; + new_st.st_fold[i + 128] = (char_u)c; if (i + 128 != c && new_st.st_isu[i + 128] && c < 256) { - new_st.st_upper[c] = i + 128; + new_st.st_upper[c] = (char_u)(i + 128); } } } @@ -5878,11 +5871,10 @@ static void set_map_str(slang_T *lp, char_u *map) if (c >= 256) { int cl = utf_char2len(c); int headcl = utf_char2len(headc); - char *b; hash_T hash; hashitem_T *hi; - b = xmalloc(cl + headcl + 2); + char *b = xmalloc((size_t)(cl + headcl) + 2); utf_char2bytes(c, b); b[cl] = NUL; utf_char2bytes(headc, b + cl + 1); diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index cf14c85d03..1c2f86a584 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -2170,6 +2170,57 @@ func Test_autocmd_nested() call assert_fails('au WinNew * nested nested echo bad', 'E983:') endfunc +func Test_autocmd_nested_cursor_invalid() + set laststatus=0 + copen + cclose + call setline(1, ['foo', 'bar', 'baz']) + 3 + augroup nested_inv + autocmd User foo ++nested copen + autocmd BufAdd * let &laststatus = 2 - &laststatus + augroup END + doautocmd User foo + + augroup nested_inv + au! + augroup END + set laststatus& + cclose + bwipe! +endfunc + +func Test_autocmd_nested_keeps_cursor_pos() + enew + call setline(1, 'foo') + autocmd User foo ++nested normal! $a + autocmd InsertLeave * : + doautocmd User foo + call assert_equal([0, 1, 3, 0], getpos('.')) + + bwipe! +endfunc + +func Test_autocmd_nested_switch_window() + " run this in a separate Vim so that SafeState works + CheckRunVimInTerminal + + let lines =<< trim END + vim9script + ['()']->writefile('Xautofile') + autocmd VimEnter * ++nested edit Xautofile | split + autocmd BufReadPost * autocmd SafeState * ++once foldclosed('.') + autocmd WinEnter * matchadd('ErrorMsg', 'pat') + END + call writefile(lines, 'Xautoscript') + let buf = RunVimInTerminal('-S Xautoscript', {'rows': 10}) + call VerifyScreenDump(buf, 'Test_autocmd_nested_switch', {}) + + call StopVimInTerminal(buf) + call delete('Xautofile') + call delete('Xautoscript') +endfunc + func Test_autocmd_once() " Without ++once WinNew triggers twice let g:did_split = 0 diff --git a/src/nvim/testdir/test_messages.vim b/src/nvim/testdir/test_messages.vim index 4be5a1b076..2f9c562771 100644 --- a/src/nvim/testdir/test_messages.vim +++ b/src/nvim/testdir/test_messages.vim @@ -118,7 +118,9 @@ func Test_message_more() let buf = RunVimInTerminal('', {'rows': 6}) call term_sendkeys(buf, ":call setline(1, range(1, 100))\n") - call term_sendkeys(buf, ":%p#\n") + call term_sendkeys(buf, ":%pfoo\<C-H>\<C-H>\<C-H>#") + call WaitForAssert({-> assert_equal(':%p#', term_getline(buf, 6))}) + call term_sendkeys(buf, "\n") call WaitForAssert({-> assert_equal(' 5 5', term_getline(buf, 5))}) call WaitForAssert({-> assert_equal('-- More --', term_getline(buf, 6))}) @@ -194,6 +196,13 @@ func Test_message_more() call WaitForAssert({-> assert_equal('100 100', term_getline(buf, 5))}) call WaitForAssert({-> assert_equal('Press ENTER or type command to continue', term_getline(buf, 6))}) + " A command line that doesn't print text is appended to scrollback, + " even if it invokes a nested command line. + call term_sendkeys(buf, ":\<C-R>=':'\<CR>:\<CR>g<") + call WaitForAssert({-> assert_equal('100 100', term_getline(buf, 4))}) + call WaitForAssert({-> assert_equal(':::', term_getline(buf, 5))}) + call WaitForAssert({-> assert_equal('Press ENTER or type command to continue', term_getline(buf, 6))}) + call term_sendkeys(buf, ":%p#\n") call WaitForAssert({-> assert_equal(' 5 5', term_getline(buf, 5))}) call WaitForAssert({-> assert_equal('-- More --', term_getline(buf, 6))}) diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index ddd4229f17..f6d573d76b 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -172,6 +172,14 @@ func XlistTests(cchar) \ ' 2 Data.Text:20 col 10 warning 22: ModuleWarning', \ ' 3 Data/Text.hs:30 col 15 warning 33: FileWarning'], l) + " Very long line should be displayed. + let text = 'Line' .. repeat('1234567890', 130) + let lines = ['Xtestfile9:2:9:' .. text] + Xgetexpr lines + + let l = split(execute('Xlist', ''), "\n") + call assert_equal([' 1 Xtestfile9:2 col 9: ' .. text] , l) + " For help entries in the quickfix list, only the filename without directory " should be displayed Xhelpgrep setqflist() diff --git a/src/nvim/window.c b/src/nvim/window.c index b43378aef2..b2812189d9 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -172,7 +172,7 @@ void do_window(int nchar, long Prenum, int xchar) CHECK_CMDWIN; reset_VIsual_and_resel(); // stop Visual mode - if (buflist_findnr(Prenum == 0 ? curwin->w_alt_fnum : Prenum) == NULL) { + if (buflist_findnr(Prenum == 0 ? curwin->w_alt_fnum : (int)Prenum) == NULL) { if (Prenum == 0) { emsg(_(e_noalt)); } else { @@ -182,7 +182,7 @@ void do_window(int nchar, long Prenum, int xchar) } if (!curbuf_locked() && win_split(0, 0) == OK) { - (void)buflist_getfile(Prenum == 0 ? curwin->w_alt_fnum : Prenum, + (void)buflist_getfile(Prenum == 0 ? curwin->w_alt_fnum : (int)Prenum, (linenr_T)0, GETF_ALT, false); } break; @@ -452,9 +452,9 @@ newwindow: case '}': CHECK_CMDWIN; if (Prenum) { - g_do_tagpreview = Prenum; + g_do_tagpreview = (int)Prenum; } else { - g_do_tagpreview = p_pvh; + g_do_tagpreview = (int)p_pvh; } FALLTHROUGH; case ']': @@ -462,7 +462,7 @@ newwindow: CHECK_CMDWIN; // Keep visual mode, can select words to use as a tag. if (Prenum) { - postponed_split = Prenum; + postponed_split = (int)Prenum; } else { postponed_split = -1; } @@ -551,16 +551,16 @@ wingotofile: case '}': xchar = Ctrl_RSB; if (Prenum) { - g_do_tagpreview = Prenum; + g_do_tagpreview = (int)Prenum; } else { - g_do_tagpreview = p_pvh; + g_do_tagpreview = (int)p_pvh; } FALLTHROUGH; case ']': case Ctrl_RSB: // Keep visual mode, can select words to use as a tag. if (Prenum) { - postponed_split = Prenum; + postponed_split = (int)Prenum; } else { postponed_split = -1; } @@ -800,8 +800,8 @@ void win_config_float(win_T *wp, FloatConfig fconfig) // compute initial position if (wp->w_float_config.relative == kFloatRelativeWindow) { - int row = wp->w_float_config.row; - int col = wp->w_float_config.col; + int row = (int)wp->w_float_config.row; + int col = (int)wp->w_float_config.col; Error dummy = ERROR_INIT; win_T *parent = find_window_by_handle(wp->w_float_config.window, &dummy); if (parent) { @@ -825,8 +825,8 @@ void win_config_float(win_T *wp, FloatConfig fconfig) wp->w_winrow = row; wp->w_wincol = col; } else { - wp->w_winrow = fconfig.row; - wp->w_wincol = fconfig.col; + wp->w_winrow = (int)fconfig.row; + wp->w_wincol = (int)fconfig.col; } // changing border style while keeping border only requires redrawing border @@ -1065,10 +1065,10 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) * width. */ // Current window requires at least 1 space. - wmw1 = (p_wmw == 0 ? 1 : p_wmw); + wmw1 = (p_wmw == 0 ? 1 : (int)p_wmw); needed = wmw1 + 1; if (flags & WSP_ROOM) { - needed += p_wiw - wmw1; + needed += (int)p_wiw - wmw1; } if (flags & (WSP_BOT | WSP_TOP)) { minwidth = frame_minwidth(topframe, NOWIN); @@ -1142,10 +1142,10 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) // Check if we are able to split the current window and compute its height. // Current window requires at least 1 space plus space for the window bar. - wmh1 = MAX(p_wmh, 1) + oldwin->w_winbar_height; + wmh1 = MAX((int)p_wmh, 1) + oldwin->w_winbar_height; needed = wmh1 + STATUS_HEIGHT; if (flags & WSP_ROOM) { - needed += p_wh - wmh1 + oldwin->w_winbar_height; + needed += (int)p_wh - wmh1 + oldwin->w_winbar_height; } if (p_ch < 1) { needed += 1; // Adjust for cmdheight=0. @@ -1305,7 +1305,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) // Need to create a new frame in the tree to make a branch. frp = xcalloc(1, sizeof(frame_T)); *frp = *curfrp; - curfrp->fr_layout = layout; + curfrp->fr_layout = (char)layout; frp->fr_parent = curfrp; frp->fr_next = NULL; frp->fr_prev = NULL; @@ -1490,12 +1490,12 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir) // Don't change the window height/width to 'winheight' / 'winwidth' if a // size was given. if (flags & WSP_VERT) { - i = p_wiw; + i = (int)p_wiw; if (size != 0) { p_wiw = size; } } else { - i = p_wh; + i = (int)p_wh; if (size != 0) { p_wh = size; } @@ -1689,14 +1689,14 @@ int make_windows(int count, bool vertical) if (vertical) { // Each window needs at least 'winminwidth' lines and a separator column. - maxcount = (curwin->w_width + curwin->w_vsep_width - - (p_wiw - p_wmw)) / (p_wmw + 1); + maxcount = (int)(curwin->w_width + curwin->w_vsep_width + - (p_wiw - p_wmw)) / ((int)p_wmw + 1); } else { // Each window needs at least 'winminheight' lines. // If statusline isn't global, each window also needs a statusline. // If 'winbar' is set, each window also needs a winbar. - maxcount = (curwin->w_height + curwin->w_hsep_height + curwin->w_status_height - - (p_wh - p_wmh)) / (p_wmh + STATUS_HEIGHT + global_winbar_height()); + maxcount = (int)(curwin->w_height + curwin->w_hsep_height + curwin->w_status_height + - (p_wh - p_wmh)) / ((int)p_wmh + STATUS_HEIGHT + global_winbar_height()); } if (maxcount < 2) { @@ -2039,10 +2039,10 @@ void win_move_after(win_T *win1, win_T *win2) static int get_maximum_wincount(frame_T *fr, int height) { if (fr->fr_layout != FR_COL) { - return (height / (p_wmh + STATUS_HEIGHT + frame2win(fr)->w_winbar_height)); + return (height / ((int)p_wmh + STATUS_HEIGHT + frame2win(fr)->w_winbar_height)); } else if (global_winbar_height()) { // If winbar is globally enabled, no need to check each window for it. - return (height / (p_wmh + STATUS_HEIGHT + 1)); + return (height / ((int)p_wmh + STATUS_HEIGHT + 1)); } frame_T *frp; @@ -2055,13 +2055,13 @@ static int get_maximum_wincount(frame_T *fr, int height) if (height < (p_wmh + STATUS_HEIGHT + wp->w_winbar_height)) { break; } - height -= p_wmh + STATUS_HEIGHT + wp->w_winbar_height; + height -= (int)p_wmh + STATUS_HEIGHT + wp->w_winbar_height; total_wincount += 1; } // If we still have enough room for more windows, just use the default winbar height (which is 0) // in order to get the amount of windows that'd fit in the remaining space - total_wincount += height / (p_wmh + STATUS_HEIGHT); + total_wincount += height / ((int)p_wmh + STATUS_HEIGHT); return total_wincount; } @@ -2134,7 +2134,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int } else { extra_sep = 0; } - totwincount = (n + extra_sep) / (p_wmw + 1); + totwincount = (n + extra_sep) / ((int)p_wmw + 1); has_next_curwin = frame_has_win(topfr, next_curwin); /* @@ -2145,7 +2145,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int m = frame_minwidth(topfr, next_curwin); room = width - m; if (room < 0) { - next_curwin_size = p_wiw + room; + next_curwin_size = (int)p_wiw + room; room = 0; } else { next_curwin_size = -1; @@ -2159,15 +2159,14 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int n = frame_minwidth(fr, NOWIN); new_size = fr->fr_width; if (frame_has_win(fr, next_curwin)) { - room += p_wiw - p_wmw; + room += (int)p_wiw - (int)p_wmw; next_curwin_size = 0; if (new_size < p_wiw) { - new_size = p_wiw; + new_size = (int)p_wiw; } } else { // These windows don't use up room. - totwincount -= (n + (fr->fr_next == NULL - ? extra_sep : 0)) / (p_wmw + 1); + totwincount -= (n + (fr->fr_next == NULL ? extra_sep : 0)) / ((int)p_wmw + 1); } room -= new_size - n; if (room < 0) { @@ -2184,12 +2183,12 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int / (totwincount - 1) > p_wiw) { // Can make all windows wider than 'winwidth', spread // the room equally. - next_curwin_size = (room + p_wiw - + (totwincount - 1) * p_wmw - + (totwincount - 1)) / totwincount; - room -= next_curwin_size - p_wiw; + next_curwin_size = (int)(room + p_wiw + + (totwincount - 1) * p_wmw + + (totwincount - 1)) / totwincount; + room -= next_curwin_size - (int)p_wiw; } else { - next_curwin_size = p_wiw; + next_curwin_size = (int)p_wiw; } } } @@ -2212,8 +2211,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int } else { // Compute the maximum number of windows horiz. in "fr". n = frame_minwidth(fr, NOWIN); - wincount = (n + (fr->fr_next == NULL ? extra_sep : 0)) - / (p_wmw + 1); + wincount = (n + (fr->fr_next == NULL ? extra_sep : 0)) / ((int)p_wmw + 1); m = frame_minwidth(fr, next_curwin); if (has_next_curwin) { hnc = frame_has_win(fr, next_curwin); @@ -2229,7 +2227,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int new_size = (wincount * room + (totwincount / 2)) / totwincount; } if (hnc) { // add next_curwin size - next_curwin_size -= p_wiw - (m - n); + next_curwin_size -= (int)p_wiw - (m - n); new_size += next_curwin_size; room -= new_size - next_curwin_size; } else { @@ -2278,7 +2276,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int if (room < 0) { // The room is less than 'winheight', use all space for the // current window. - next_curwin_size = p_wh + room; + next_curwin_size = (int)p_wh + room; room = 0; } else { next_curwin_size = -1; @@ -2292,10 +2290,10 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int n = frame_minheight(fr, NOWIN); new_size = fr->fr_height; if (frame_has_win(fr, next_curwin)) { - room += p_wh - p_wmh; + room += (int)p_wh - (int)p_wmh; next_curwin_size = 0; if (new_size < p_wh) { - new_size = p_wh; + new_size = (int)p_wh; } } else { // These windows don't use up room. @@ -2316,12 +2314,12 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int / (totwincount - 1) > p_wh) { // can make all windows higher than 'winheight', // spread the room equally. - next_curwin_size = (room + p_wh - + (totwincount - 1) * p_wmh - + (totwincount - 1)) / totwincount; - room -= next_curwin_size - p_wh; + next_curwin_size = (int)(room + p_wh + + (totwincount - 1) * p_wmh + + (totwincount - 1)) / totwincount; + room -= next_curwin_size - (int)p_wh; } else { - next_curwin_size = p_wh; + next_curwin_size = (int)p_wh; } } } @@ -2360,7 +2358,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int new_size = (wincount * room + (totwincount / 2)) / totwincount; } if (hnc) { // add next_curwin size - next_curwin_size -= p_wh - (m - n); + next_curwin_size -= (int)p_wh - (m - n); new_size += next_curwin_size; room -= new_size - next_curwin_size; } else { @@ -3775,9 +3773,9 @@ static int frame_minheight(frame_T *topfrp, win_T *next_curwin) + topfrp->fr_win->w_status_height; if (topfrp->fr_win == next_curwin) { - m = p_wh + extra_height; + m = (int)p_wh + extra_height; } else { - m = p_wmh + extra_height; + m = (int)p_wmh + extra_height; if (topfrp->fr_win == curwin && next_curwin == NULL) { // Current window is minimal one line high. if (p_wmh == 0) { @@ -3818,10 +3816,10 @@ static int frame_minwidth(frame_T *topfrp, win_T *next_curwin) if (topfrp->fr_win != NULL) { if (topfrp->fr_win == next_curwin) { - m = p_wiw + topfrp->fr_win->w_vsep_width; + m = (int)p_wiw + topfrp->fr_win->w_vsep_width; } else { // window: minimal width of the window plus separator column - m = p_wmw + topfrp->fr_win->w_vsep_width; + m = (int)p_wmw + topfrp->fr_win->w_vsep_width; // Current window is minimal one column wide if (p_wmw == 0 && topfrp->fr_win == curwin && next_curwin == NULL) { ++m; @@ -3978,7 +3976,7 @@ static int win_alloc_firstwin(win_T *oldwin) new_frame(curwin); topframe = curwin->w_frame; topframe->fr_width = Columns; - topframe->fr_height = Rows - p_ch - global_stl_height(); + topframe->fr_height = Rows - (int)p_ch - global_stl_height(); return OK; } @@ -4000,11 +3998,11 @@ static void new_frame(win_T *wp) */ void win_init_size(void) { - firstwin->w_height = ROWS_AVAIL; + firstwin->w_height = (int)ROWS_AVAIL; firstwin->w_height_inner = firstwin->w_height - firstwin->w_winbar_height; firstwin->w_height_outer = firstwin->w_height; firstwin->w_winrow_off = firstwin->w_winbar_height; - topframe->fr_height = ROWS_AVAIL; + topframe->fr_height = (int)ROWS_AVAIL; firstwin->w_width = Columns; firstwin->w_width_inner = firstwin->w_width; firstwin->w_width_outer = firstwin->w_width; @@ -4163,7 +4161,7 @@ int make_tabpages(int maxcount) // Limit to 'tabpagemax' tabs. if (count > p_tpm) { - count = p_tpm; + count = (int)p_tpm; } /* @@ -5114,10 +5112,10 @@ static void win_free(win_T *wp, tabpage_T *tp) xfree(wp->w_localdir); xfree(wp->w_prevdir); - stl_clear_click_defs(wp->w_status_click_defs, wp->w_status_click_defs_size); + stl_clear_click_defs(wp->w_status_click_defs, (long)wp->w_status_click_defs_size); xfree(wp->w_status_click_defs); - stl_clear_click_defs(wp->w_winbar_click_defs, wp->w_winbar_click_defs_size); + stl_clear_click_defs(wp->w_winbar_click_defs, (long)wp->w_winbar_click_defs_size); xfree(wp->w_winbar_click_defs); // Remove the window from the b_wininfo lists, it may happen that the @@ -5499,7 +5497,7 @@ void win_setheight_win(int height, win_T *win) { // Always keep current window at least one line high, even when 'winminheight' is zero. // Keep window at least two lines high if 'winbar' is enabled. - height = MAX(height, (win == curwin ? MAX(p_wmh, 1) : p_wmh) + win->w_winbar_height); + height = MAX(height, (int)(win == curwin ? MAX(p_wmh, 1) : p_wmh) + win->w_winbar_height); if (win->w_floating) { win->w_float_config.height = height; @@ -5562,7 +5560,7 @@ static void frame_setheight(frame_T *curfrp, int height) // If height is greater than the available space, try to create space for // the frame by reducing 'cmdheight' if possible, while making sure // `cmdheight` doesn't go below 1. - height = MIN((p_ch > 0 ? ROWS_AVAIL + (p_ch - 1) : ROWS_AVAIL), height); + height = (int)MIN((p_ch > 0 ? ROWS_AVAIL + (p_ch - 1) : ROWS_AVAIL), height); } if (height > 0) { frame_new_height(curfrp, height, false, false); @@ -5604,7 +5602,7 @@ static void frame_setheight(frame_T *curfrp, int height) room_cmdline = 0; } else { win_T *wp = lastwin_nofloating(); - room_cmdline = Rows - p_ch - global_stl_height() + room_cmdline = Rows - (int)p_ch - global_stl_height() - (wp->w_winrow + wp->w_height + wp->w_hsep_height + wp->w_status_height); if (room_cmdline < 0) { room_cmdline = 0; @@ -5714,7 +5712,7 @@ void win_setwidth_win(int width, win_T *wp) // 'winminwidth' is zero. if (wp == curwin) { if (width < p_wmw) { - width = p_wmw; + width = (int)p_wmw; } if (width == 0) { width = 1; @@ -5878,7 +5876,7 @@ void win_setminheight(void) // loop until there is a 'winminheight' that is possible while (p_wmh > 0) { - const int room = Rows - p_ch; + const int room = Rows - (int)p_ch; const int needed = min_rows() - 1; // 1 was added for the cmdline if (room >= needed) { break; @@ -5969,7 +5967,7 @@ void win_drag_status_line(win_T *dragwin, int offset) // Only dragging the last status line can reduce p_ch. room = Rows - cmdline_row; if (curfr->fr_next != NULL) { - room -= p_ch + global_stl_height(); + room -= (int)p_ch + global_stl_height(); } if (room < 0) { room = 0; @@ -6147,8 +6145,7 @@ void set_fraction(win_T *wp) // When cursor is in the first line the percentage is computed as if // it's halfway that line. Thus with two lines it is 25%, with three // lines 17%, etc. Similarly for the last line: 75%, 83%, etc. - wp->w_fraction = ((long)wp->w_wrow * FRACTION_MULT + FRACTION_MULT / 2) - / (long)wp->w_height_inner; + wp->w_fraction = (int)(wp->w_wrow * FRACTION_MULT + FRACTION_MULT / 2) / wp->w_height_inner; } } @@ -6195,7 +6192,7 @@ void scroll_to_fraction(win_T *wp, int prev_height) if (lnum < 1) { // can happen when starting up lnum = 1; } - wp->w_wrow = ((long)wp->w_fraction * (long)height - 1L) / FRACTION_MULT; + wp->w_wrow = (int)((long)wp->w_fraction * (long)height - 1L) / FRACTION_MULT; line_size = plines_win_col(wp, lnum, (long)(wp->w_cursor.col)) - 1; sline = wp->w_wrow - line_size; @@ -6380,7 +6377,7 @@ void command_height(void) { int h; frame_T *frp; - int old_p_ch = curtab->tp_ch_used; + int old_p_ch = (int)curtab->tp_ch_used; // Use the value of p_ch that we remembered. This is needed for when the // GUI starts up, we can't be sure in what order things happen. And when @@ -6400,7 +6397,7 @@ void command_height(void) } if (starting != NO_SCREEN) { - cmdline_row = Rows - p_ch; + cmdline_row = Rows - (int)p_ch; if (p_ch > old_p_ch) { // p_ch got bigger while (p_ch > old_p_ch) { @@ -6408,12 +6405,12 @@ void command_height(void) emsg(_(e_noroom)); p_ch = old_p_ch; curtab->tp_ch_used = p_ch; - cmdline_row = Rows - p_ch; + cmdline_row = Rows - (int)p_ch; break; } h = frp->fr_height - frame_minheight(frp, NULL); if (h > p_ch - old_p_ch) { - h = p_ch - old_p_ch; + h = (int)p_ch - old_p_ch; } old_p_ch += h; frame_add_height(frp, -h); @@ -6479,7 +6476,7 @@ char_u *grab_file_name(long count, linenr_T *file_lnum) if (file_lnum != NULL && ptr[len] == ':' && isdigit(ptr[len + 1])) { char_u *p = ptr + len + 1; - *file_lnum = getdigits_long(&p, false, 0); + *file_lnum = (linenr_T)getdigits_long(&p, false, 0); } return find_file_name_in_path(ptr, len, options, count, (char_u *)curbuf->b_ffname); } @@ -6603,7 +6600,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u } p = skipwhite(p); if (isdigit(*p)) { - *file_lnum = getdigits_long((char_u **)&p, false, 0); + *file_lnum = (linenr_T)getdigits_long((char_u **)&p, false, 0); } } } @@ -6633,7 +6630,7 @@ static void win_remove_status_line(win_T *wp, bool add_hsep) } comp_col(); - stl_clear_click_defs(wp->w_status_click_defs, wp->w_status_click_defs_size); + stl_clear_click_defs(wp->w_status_click_defs, (long)wp->w_status_click_defs_size); xfree(wp->w_status_click_defs); wp->w_status_click_defs_size = 0; wp->w_status_click_defs = NULL; @@ -6767,7 +6764,7 @@ int set_winbar_win(win_T *wp, bool make_room) if (winbar_height == 0) { // When removing winbar, deallocate the w_winbar_click_defs array - stl_clear_click_defs(wp->w_winbar_click_defs, wp->w_winbar_click_defs_size); + stl_clear_click_defs(wp->w_winbar_click_defs, (long)wp->w_winbar_click_defs_size); xfree(wp->w_winbar_click_defs); wp->w_winbar_click_defs_size = 0; wp->w_winbar_click_defs = NULL; @@ -6858,43 +6855,67 @@ bool only_one_window(void) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT return count <= 1; } -/// Correct the cursor line number in other windows. Used after changing the -/// current buffer, and before applying autocommands. -/// -/// @param do_curwin when true, also check current window. -void check_lnums(bool do_curwin) +/// Implementation of check_lnums() and check_lnums_nested(). +static void check_lnums_both(bool do_curwin, bool nested) { FOR_ALL_TAB_WINDOWS(tp, wp) { if ((do_curwin || wp != curwin) && wp->w_buffer == curbuf) { - // save the original cursor position and topline - wp->w_save_cursor.w_cursor_save = wp->w_cursor; - wp->w_save_cursor.w_topline_save = wp->w_topline; + if (!nested) { + // save the original cursor position and topline + wp->w_save_cursor.w_cursor_save = wp->w_cursor; + wp->w_save_cursor.w_topline_save = wp->w_topline; + } - if (wp->w_cursor.lnum > curbuf->b_ml.ml_line_count) { + bool need_adjust = wp->w_cursor.lnum > curbuf->b_ml.ml_line_count; + if (need_adjust) { wp->w_cursor.lnum = curbuf->b_ml.ml_line_count; } - if (wp->w_topline > curbuf->b_ml.ml_line_count) { - wp->w_topline = curbuf->b_ml.ml_line_count; + if (need_adjust || !nested) { + // save the (corrected) cursor position + wp->w_save_cursor.w_cursor_corr = wp->w_cursor; } - // save the corrected cursor position and topline - wp->w_save_cursor.w_cursor_corr = wp->w_cursor; - wp->w_save_cursor.w_topline_corr = wp->w_topline; + need_adjust = wp->w_topline > curbuf->b_ml.ml_line_count; + if (need_adjust) { + wp->w_topline = curbuf->b_ml.ml_line_count; + } + if (need_adjust || !nested) { + // save the (corrected) topline + wp->w_save_cursor.w_topline_corr = wp->w_topline; + } } } } +/// Correct the cursor line number in other windows. Used after changing the +/// current buffer, and before applying autocommands. +/// +/// @param do_curwin when true, also check current window. +void check_lnums(bool do_curwin) +{ + check_lnums_both(do_curwin, false); +} + +/// Like check_lnums() but for when check_lnums() was already called. +void check_lnums_nested(bool do_curwin) +{ + check_lnums_both(do_curwin, true); +} + /// Reset cursor and topline to its stored values from check_lnums(). /// check_lnums() must have been called first! void reset_lnums(void) { FOR_ALL_TAB_WINDOWS(tp, wp) { if (wp->w_buffer == curbuf) { - // Restore the value if the autocommand didn't change it. - if (equalpos(wp->w_save_cursor.w_cursor_corr, wp->w_cursor)) { + // Restore the value if the autocommand didn't change it and it was + // set. + if (equalpos(wp->w_save_cursor.w_cursor_corr, wp->w_cursor) + && wp->w_save_cursor.w_cursor_save.lnum != 0) { wp->w_cursor = wp->w_save_cursor.w_cursor_save; } - if (wp->w_save_cursor.w_topline_corr == wp->w_topline) { + if (wp->w_save_cursor.w_topline_corr == wp->w_topline + && wp->w_save_cursor.w_topline_save != 0) { wp->w_topline = wp->w_save_cursor.w_topline_save; } } @@ -7213,14 +7234,14 @@ int win_getid(typval_T *argvars) if (argvars[0].v_type == VAR_UNKNOWN) { return curwin->handle; } - int winnr = tv_get_number(&argvars[0]); + int winnr = (int)tv_get_number(&argvars[0]); win_T *wp; if (winnr > 0) { if (argvars[1].v_type == VAR_UNKNOWN) { wp = firstwin; } else { tabpage_T *tp = NULL; - int tabnr = tv_get_number(&argvars[1]); + int tabnr = (int)tv_get_number(&argvars[1]); FOR_ALL_TABS(tp2) { if (--tabnr == 0) { tp = tp2; @@ -7247,7 +7268,7 @@ int win_getid(typval_T *argvars) int win_gotoid(typval_T *argvars) { - int id = tv_get_number(&argvars[0]); + int id = (int)tv_get_number(&argvars[0]); FOR_ALL_TAB_WINDOWS(tp, wp) { if (wp->handle == id) { @@ -7314,7 +7335,7 @@ win_T *win_id2wp_tp(int id, tabpage_T **tpp) int win_id2win(typval_T *argvars) { int nr = 1; - int id = tv_get_number(&argvars[0]); + int id = (int)tv_get_number(&argvars[0]); FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { if (wp->handle == id) { @@ -7327,7 +7348,7 @@ int win_id2win(typval_T *argvars) void win_findbuf(typval_T *argvars, list_T *list) { - int bufnr = tv_get_number(&argvars[0]); + int bufnr = (int)tv_get_number(&argvars[0]); FOR_ALL_TAB_WINDOWS(tp, wp) { if (wp->w_buffer->b_fnum == bufnr) { diff --git a/test/functional/legacy/messages_spec.lua b/test/functional/legacy/messages_spec.lua index 7bcbecc582..51c2406933 100644 --- a/test/functional/legacy/messages_spec.lua +++ b/test/functional/legacy/messages_spec.lua @@ -27,7 +27,16 @@ describe('messages', function() it('works', function() command('call setline(1, range(1, 100))') - feed(':%p#\n') + feed(':%pfoo<C-H><C-H><C-H>#') + screen:expect([[ + 1 | + 2 | + 3 | + 4 | + 5 | + :%p#^ | + ]]) + feed('\n') screen:expect([[ {2: 1 }1 | {2: 2 }2 | @@ -241,6 +250,18 @@ describe('messages', function() {1:Press ENTER or type command to continue}^ | ]]) + -- A command line that doesn't print text is appended to scrollback, + -- even if it invokes a nested command line. + feed([[:<C-R>=':'<CR>:<CR>g<lt>]]) + screen:expect([[ + {2: 97 }97 | + {2: 98 }98 | + {2: 99 }99 | + {2:100 }100 | + ::: | + {1:Press ENTER or type command to continue}^ | + ]]) + feed(':%p#\n') screen:expect([[ {2: 1 }1 | |