aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mpack/mpack_core.c3
-rwxr-xr-xsrc/nvim/CMakeLists.txt126
-rw-r--r--src/nvim/api/autocmd.c2
-rw-r--r--src/nvim/api/extmark.c2
-rw-r--r--src/nvim/api/keysets.lua95
-rw-r--r--src/nvim/api/private/converter.c2
-rw-r--r--src/nvim/api/private/helpers.c14
-rw-r--r--src/nvim/api/ui.c7
-rw-r--r--src/nvim/api/vim.c4
-rw-r--r--src/nvim/api/win_config.c2
-rw-r--r--src/nvim/api/window.c7
-rw-r--r--src/nvim/auevents.lua20
-rw-r--r--src/nvim/buffer.c174
-rw-r--r--src/nvim/buffer_defs.h1
-rw-r--r--src/nvim/change.c17
-rw-r--r--src/nvim/charset.c22
-rw-r--r--src/nvim/cmdexpand.c672
-rw-r--r--src/nvim/cmdexpand.h4
-rw-r--r--src/nvim/cmdhist.c18
-rw-r--r--src/nvim/context.c4
-rw-r--r--src/nvim/debugger.c12
-rw-r--r--src/nvim/decoration.c13
-rw-r--r--src/nvim/decoration.h2
-rw-r--r--src/nvim/diff.c8
-rw-r--r--src/nvim/digraph.c40
-rw-r--r--src/nvim/drawline.c148
-rw-r--r--src/nvim/drawscreen.c42
-rw-r--r--src/nvim/edit.c96
-rw-r--r--src/nvim/eval.c270
-rw-r--r--src/nvim/eval.h2
-rw-r--r--src/nvim/eval.lua69
-rw-r--r--src/nvim/eval/buffer.c5
-rw-r--r--src/nvim/eval/encode.c2
-rw-r--r--src/nvim/eval/encode.h1
-rw-r--r--src/nvim/eval/executor.c4
-rw-r--r--src/nvim/eval/funcs.c155
-rw-r--r--src/nvim/eval/typval.c117
-rw-r--r--src/nvim/eval/typval.h12
-rw-r--r--src/nvim/eval/typval_defs.h2
-rw-r--r--src/nvim/eval/typval_encode.c.h4
-rw-r--r--src/nvim/eval/userfunc.c144
-rw-r--r--src/nvim/eval/vars.c84
-rw-r--r--src/nvim/eval/window.c3
-rw-r--r--src/nvim/eval/window.h10
-rw-r--r--src/nvim/event/libuv_process.c2
-rw-r--r--src/nvim/event/process.c1
-rw-r--r--src/nvim/ex_cmds.c34
-rw-r--r--src/nvim/ex_cmds.lua2
-rw-r--r--src/nvim/ex_docmd.c160
-rw-r--r--src/nvim/ex_eval.c9
-rw-r--r--src/nvim/ex_getln.c144
-rw-r--r--src/nvim/ex_getln.h4
-rw-r--r--src/nvim/ex_session.c72
-rw-r--r--src/nvim/file_search.c48
-rw-r--r--src/nvim/fileio.c457
-rw-r--r--src/nvim/fold.c2
-rw-r--r--src/nvim/fold.h2
-rw-r--r--src/nvim/garray.c8
-rw-r--r--src/nvim/garray.h3
-rw-r--r--src/nvim/generators/gen_api_dispatch.lua4
-rw-r--r--src/nvim/generators/gen_eval.lua9
-rw-r--r--src/nvim/generators/gen_events.lua4
-rw-r--r--src/nvim/generators/gen_keysets.lua5
-rw-r--r--src/nvim/generators/gen_options.lua6
-rw-r--r--src/nvim/getchar.c50
-rw-r--r--src/nvim/globals.h12
-rw-r--r--src/nvim/grid.c12
-rw-r--r--src/nvim/hashtab.c17
-rw-r--r--src/nvim/help.c18
-rw-r--r--src/nvim/highlight.c58
-rw-r--r--src/nvim/highlight_defs.h18
-rw-r--r--src/nvim/highlight_group.c158
-rw-r--r--src/nvim/iconv.h20
-rw-r--r--src/nvim/indent.c55
-rw-r--r--src/nvim/indent_c.c3
-rw-r--r--src/nvim/input.c3
-rw-r--r--src/nvim/insexpand.c44
-rw-r--r--src/nvim/keycodes.c44
-rw-r--r--src/nvim/linematch.c1
-rw-r--r--src/nvim/locale.c4
-rw-r--r--src/nvim/lua/converter.c2
-rw-r--r--src/nvim/lua/executor.c92
-rw-r--r--src/nvim/lua/spell.c2
-rw-r--r--src/nvim/lua/stdlib.c33
-rw-r--r--src/nvim/lua/treesitter.c4
-rw-r--r--src/nvim/main.c68
-rw-r--r--src/nvim/main.h3
-rw-r--r--src/nvim/mapping.c203
-rw-r--r--src/nvim/mark.c27
-rw-r--r--src/nvim/marktree.c2
-rw-r--r--src/nvim/mbyte.c193
-rw-r--r--src/nvim/mbyte_defs.h2
-rw-r--r--src/nvim/memfile.c1
-rw-r--r--src/nvim/memline.c48
-rw-r--r--src/nvim/memory.c1
-rw-r--r--src/nvim/menu.c1
-rw-r--r--src/nvim/message.c8
-rw-r--r--src/nvim/mouse.c55
-rw-r--r--src/nvim/move.c4
-rw-r--r--src/nvim/msgpack_rpc/channel.c3
-rw-r--r--src/nvim/msgpack_rpc/server.c2
-rw-r--r--src/nvim/normal.c789
-rw-r--r--src/nvim/normal.h1
-rw-r--r--src/nvim/ops.c188
-rw-r--r--src/nvim/option.c1832
-rw-r--r--src/nvim/option_defs.h53
-rw-r--r--src/nvim/optionstr.c2152
-rw-r--r--src/nvim/os/env.c16
-rw-r--r--src/nvim/os/fileio.c2
-rw-r--r--src/nvim/os/fs.c25
-rw-r--r--src/nvim/os/input.c21
-rw-r--r--src/nvim/os/input.h2
-rw-r--r--src/nvim/os/nvim.manifest20
-rw-r--r--src/nvim/os/os_win_console.c17
-rw-r--r--src/nvim/os/shell.c12
-rw-r--r--src/nvim/os/stdpaths.c2
-rw-r--r--src/nvim/path.c127
-rw-r--r--src/nvim/plines.c5
-rw-r--r--src/nvim/po/tr.po3
-rw-r--r--src/nvim/po/uk.po3
-rw-r--r--src/nvim/po/zh_CN.UTF-8.po17
-rw-r--r--src/nvim/popupmenu.c32
-rw-r--r--src/nvim/profile.c51
-rw-r--r--src/nvim/quickfix.c310
-rw-r--r--src/nvim/regexp.c177
-rw-r--r--src/nvim/regexp_bt.c286
-rw-r--r--src/nvim/regexp_nfa.c260
-rw-r--r--src/nvim/runtime.c292
-rw-r--r--src/nvim/runtime.h1
-rw-r--r--src/nvim/screen.c107
-rw-r--r--src/nvim/search.c486
-rw-r--r--src/nvim/search.h8
-rw-r--r--src/nvim/sha256.c28
-rw-r--r--src/nvim/sha256.h2
-rw-r--r--src/nvim/shada.c14
-rw-r--r--src/nvim/sign.c26
-rw-r--r--src/nvim/sign_defs.h6
-rw-r--r--src/nvim/spell.c425
-rw-r--r--src/nvim/spell_defs.h28
-rw-r--r--src/nvim/spellfile.c618
-rw-r--r--src/nvim/spellsuggest.c236
-rw-r--r--src/nvim/statusline.c67
-rw-r--r--src/nvim/strings.c22
-rw-r--r--src/nvim/syntax.c146
-rw-r--r--src/nvim/tag.c250
-rw-r--r--src/nvim/terminal.c14
-rw-r--r--src/nvim/testdir/check.vim4
-rwxr-xr-xsrc/nvim/testdir/runnvim.sh3
-rw-r--r--src/nvim/testdir/test_autocmd.vim3
-rw-r--r--src/nvim/testdir/test_breakindent.vim40
-rw-r--r--src/nvim/testdir/test_buffer.vim6
-rw-r--r--src/nvim/testdir/test_cmdline.vim853
-rw-r--r--src/nvim/testdir/test_const.vim8
-rw-r--r--src/nvim/testdir/test_cursorline.vim2
-rw-r--r--src/nvim/testdir/test_debugger.vim2
-rw-r--r--src/nvim/testdir/test_edit.vim15
-rw-r--r--src/nvim/testdir/test_filetype.vim10
-rw-r--r--src/nvim/testdir/test_fold.vim71
-rw-r--r--src/nvim/testdir/test_gf.vim25
-rw-r--r--src/nvim/testdir/test_ins_complete.vim27
-rw-r--r--src/nvim/testdir/test_listdict.vim13
-rw-r--r--src/nvim/testdir/test_normal.vim46
-rw-r--r--src/nvim/testdir/test_options.vim24
-rw-r--r--src/nvim/testdir/test_packadd.vim84
-rw-r--r--src/nvim/testdir/test_profile.vim41
-rw-r--r--src/nvim/testdir/test_search.vim16
-rw-r--r--src/nvim/testdir/test_search_stat.vim23
-rw-r--r--src/nvim/testdir/test_shell.vim209
-rw-r--r--src/nvim/testdir/test_spell.vim17
-rw-r--r--src/nvim/testdir/test_startup.vim35
-rw-r--r--src/nvim/testdir/test_substitute.vim13
-rw-r--r--src/nvim/testdir/test_system.vim36
-rw-r--r--src/nvim/testdir/test_taglist.vim4
-rw-r--r--src/nvim/testdir/test_utf8.vim53
-rw-r--r--src/nvim/testdir/test_virtualedit.vim13
-rw-r--r--src/nvim/testdir/test_visual.vim11
-rw-r--r--src/nvim/testdir/test_writefile.vim12
-rw-r--r--src/nvim/testing.c89
-rw-r--r--src/nvim/textformat.c59
-rw-r--r--src/nvim/textobject.c6
-rw-r--r--src/nvim/tui/input.c42
-rw-r--r--src/nvim/tui/input.h8
-rw-r--r--src/nvim/tui/terminfo.c6
-rw-r--r--src/nvim/tui/tui.c47
-rw-r--r--src/nvim/ui.c9
-rw-r--r--src/nvim/ui_client.c18
-rw-r--r--src/nvim/ui_client.h8
-rw-r--r--src/nvim/ui_compositor.c1
-rw-r--r--src/nvim/undo.c80
-rw-r--r--src/nvim/usercmd.c7
-rw-r--r--src/nvim/version.c63
-rw-r--r--src/nvim/vim.h3
-rw-r--r--src/nvim/viml/parser/expressions.c3
-rw-r--r--src/nvim/window.c104
-rw-r--r--src/nvim/window.h1
195 files changed, 9448 insertions, 6692 deletions
diff --git a/src/mpack/mpack_core.c b/src/mpack/mpack_core.c
index 4ee67a032a..3424f444b9 100644
--- a/src/mpack/mpack_core.c
+++ b/src/mpack/mpack_core.c
@@ -173,6 +173,9 @@ MPACK_API int mpack_write(mpack_tokbuf_t *tokbuf, char **buf, size_t *buflen,
int mpack_rtoken(const char **buf, size_t *buflen, mpack_token_t *tok)
{
+ if (*buflen == 0) {
+ return MPACK_EOF;
+ }
unsigned char t = ADVANCE(buf, buflen);
if (t < 0x80) {
/* positive fixint */
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index b95709526b..7b56af59da 100755
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -22,24 +22,19 @@ find_package(TreeSitter REQUIRED)
target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${TreeSitter_INCLUDE_DIRS})
target_link_libraries(main_lib INTERFACE ${TreeSitter_LIBRARIES})
-find_package(UNIBILIUM 2.0 REQUIRED)
-target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${UNIBILIUM_INCLUDE_DIRS})
-target_link_libraries(main_lib INTERFACE ${UNIBILIUM_LIBRARIES})
+find_package(unibilium 2.0 REQUIRED)
+target_link_libraries(main_lib INTERFACE unibilium)
find_package(LibTermkey 0.22 REQUIRED)
target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LIBTERMKEY_INCLUDE_DIRS})
target_link_libraries(main_lib INTERFACE ${LIBTERMKEY_LIBRARIES})
-find_package(LIBVTERM 0.3 REQUIRED)
-target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LIBVTERM_INCLUDE_DIRS})
-target_link_libraries(main_lib INTERFACE ${LIBVTERM_LIBRARIES})
+find_package(libvterm 0.3 REQUIRED)
+target_link_libraries(main_lib INTERFACE libvterm)
-if(Iconv_FOUND)
- target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${Iconv_INCLUDE_DIRS})
- if(Iconv_LIBRARIES)
- target_link_libraries(main_lib INTERFACE ${Iconv_LIBRARIES})
- endif()
-endif()
+find_package(Iconv REQUIRED)
+target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${Iconv_INCLUDE_DIRS})
+target_link_libraries(main_lib INTERFACE ${Iconv_LIBRARIES})
option(ENABLE_LIBINTL "enable libintl" ON)
if(ENABLE_LIBINTL)
@@ -57,7 +52,7 @@ if(PREFER_LUA)
find_package(Lua 5.1 EXACT REQUIRED)
target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LUA_INCLUDE_DIR})
target_link_libraries(main_lib INTERFACE ${LUA_LIBRARIES})
- # Passive (not REQUIRED): if LUAJIT_FOUND is not set, nvim-test is skipped.
+ # Passive (not REQUIRED): if LUAJIT_FOUND is not set, fixtures for unittests is skipped.
find_package(LuaJit)
else()
find_package(LuaJit REQUIRED)
@@ -65,12 +60,6 @@ else()
target_link_libraries(main_lib INTERFACE ${LUAJIT_LIBRARIES})
endif()
-# Determine platform's threading library. Set CMAKE_THREAD_PREFER_PTHREAD
-# explicitly to indicate a strong preference for pthread.
-set(CMAKE_THREAD_PREFER_PTHREAD ON)
-find_package(Threads REQUIRED)
-target_link_libraries(main_lib INTERFACE ${CMAKE_THREAD_LIBS_INIT})
-
option(ENABLE_IWYU "Run include-what-you-use with the compiler." OFF)
if(ENABLE_IWYU)
find_program(IWYU_PRG NAMES include-what-you-use iwyu)
@@ -85,13 +74,18 @@ if(ENABLE_IWYU)
string(APPEND iwyu_flags "-Xiwyu;--mapping_file=${PROJECT_SOURCE_DIR}/cmake.config/iwyu/gcc.symbols.imp")
set_target_properties(nvim PROPERTIES C_INCLUDE_WHAT_YOU_USE "${iwyu_flags}")
- target_compile_definitions(nvim PRIVATE EXITFREE)
+ target_compile_definitions(main_lib INTERFACE EXITFREE)
endif()
if(MSVC)
- # XXX: /W4 gives too many warnings. #3241
- target_compile_options(main_lib INTERFACE -W1 -wd4311)
+ # TODO(dundargoc): bump warning level
+ target_compile_options(main_lib INTERFACE -W2)
+
+ # Disable warnings that give too many false positives.
+ target_compile_options(main_lib INTERFACE -wd4311 -wd4146)
target_compile_definitions(main_lib INTERFACE _CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_DEPRECATE)
+
+ target_sources(main_lib INTERFACE ${CMAKE_CURRENT_LIST_DIR}/os/nvim.manifest)
else()
target_compile_options(main_lib INTERFACE -Wall -Wextra -pedantic -Wno-unused-parameter
-Wstrict-prototypes -std=gnu99 -Wshadow -Wconversion
@@ -179,24 +173,6 @@ if(CI_BUILD)
endif()
endif()
-list(APPEND CMAKE_REQUIRED_INCLUDES "${UNIBILIUM_INCLUDE_DIRS}")
-list(APPEND CMAKE_REQUIRED_LIBRARIES "${UNIBILIUM_LIBRARIES}")
-check_c_source_compiles("
-#include <unibilium.h>
-
-int
-main(void)
-{
- unibi_str_from_var(unibi_var_from_str(\"\"));
- return unibi_num_from_var(unibi_var_from_num(0));
-}
-" UNIBI_HAS_VAR_FROM)
-list(REMOVE_ITEM CMAKE_REQUIRED_INCLUDES "${UNIBILIUM_INCLUDE_DIRS}")
-list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "${UNIBILIUM_LIBRARIES}")
-if(UNIBI_HAS_VAR_FROM)
- target_compile_definitions(main_lib INTERFACE NVIM_UNIBI_HAS_VAR_FROM)
-endif()
-
list(APPEND CMAKE_REQUIRED_INCLUDES "${MSGPACK_INCLUDE_DIRS}")
check_c_source_compiles("
#include <msgpack.h>
@@ -455,8 +431,11 @@ endforeach()
list(REMOVE_ITEM NVIM_SOURCES ${to_remove})
-if(NOT MSVC)
- # xdiff, mpack, lua-cjson: inlined external project, we don't maintain it. #9306
+# xdiff, mpack, lua-cjson: inlined external project, we don't maintain it. #9306
+if(MSVC)
+ set_source_files_properties(
+ ${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} /wd4090 /wd4244")
+else()
set_source_files_properties(
${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion -Wno-missing-noreturn -Wno-missing-format-attribute -Wno-double-promotion -Wno-strict-prototypes")
endif()
@@ -564,11 +543,11 @@ add_custom_command(OUTPUT ${GENERATED_UNICODE_TABLES}
add_custom_command(
OUTPUT ${GENERATED_API_DISPATCH} ${GENERATED_FUNCS_METADATA}
${API_METADATA} ${LUA_API_C_BINDINGS}
- COMMAND ${LUA_PRG} ${API_DISPATCH_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}
- ${GENERATED_API_DISPATCH}
- ${GENERATED_FUNCS_METADATA} ${API_METADATA}
- ${LUA_API_C_BINDINGS}
- ${API_HEADERS}
+ COMMAND ${LUA_GEN_PRG} ${API_DISPATCH_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}
+ ${GENERATED_API_DISPATCH}
+ ${GENERATED_FUNCS_METADATA} ${API_METADATA}
+ ${LUA_API_C_BINDINGS}
+ ${API_HEADERS}
DEPENDS
${API_HEADERS}
${MSGPACK_RPC_HEADERS}
@@ -613,12 +592,12 @@ add_custom_command(
${GENERATED_UI_EVENTS_REMOTE}
${GENERATED_UI_EVENTS_METADATA}
${GENERATED_UI_EVENTS_CLIENT}
- COMMAND ${LUA_PRG} ${API_UI_EVENTS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}
- ${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h
- ${GENERATED_UI_EVENTS_CALL}
- ${GENERATED_UI_EVENTS_REMOTE}
- ${GENERATED_UI_EVENTS_METADATA}
- ${GENERATED_UI_EVENTS_CLIENT}
+ COMMAND ${LUA_GEN_PRG} ${API_UI_EVENTS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}
+ ${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h
+ ${GENERATED_UI_EVENTS_CALL}
+ ${GENERATED_UI_EVENTS_REMOTE}
+ ${GENERATED_UI_EVENTS_METADATA}
+ ${GENERATED_UI_EVENTS_CLIENT}
DEPENDS
${API_UI_EVENTS_GENERATOR}
${GENERATOR_C_GRAMMAR}
@@ -685,8 +664,6 @@ foreach(hfile ${NVIM_GENERATED_FOR_HEADERS})
endif()
endforeach()
-# Our dependencies come first.
-
if (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
target_link_libraries(main_lib INTERFACE pthread c++abi)
endif()
@@ -702,6 +679,14 @@ if(UNIX)
endif()
endif()
+if(NOT LUAJIT_FOUND)
+ message(STATUS "luajit not found, skipping unit tests")
+elseif(CMAKE_BUILD_TYPE MATCHES Debug)
+ glob_wrapper(UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c)
+ list(APPEND NVIM_SOURCES ${UNIT_TEST_FIXTURES})
+ target_compile_definitions(main_lib INTERFACE UNIT_TESTING)
+endif()
+
target_sources(nvim PRIVATE ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS}
${NVIM_GENERATED_SOURCES} ${NVIM_SOURCES} ${NVIM_HEADERS}
${EXTERNAL_SOURCES} ${EXTERNAL_HEADERS})
@@ -855,38 +840,11 @@ endif()
set_target_properties(
libnvim
PROPERTIES
- POSITION_INDEPENDENT_CODE ON
OUTPUT_NAME ${LIBNVIM_NAME}
)
target_compile_definitions(libnvim PRIVATE MAKE_LIB)
target_link_libraries(libnvim PRIVATE main_lib PUBLIC libuv_lib)
-if(NOT LUAJIT_FOUND)
- message(STATUS "luajit not found, skipping nvim-test (unit tests) target")
-else()
- glob_wrapper(UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c)
- add_library(
- nvim-test
- MODULE
- EXCLUDE_FROM_ALL
- ${NVIM_SOURCES} ${NVIM_GENERATED_SOURCES}
- ${NVIM_HEADERS} ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS}
- ${EXTERNAL_SOURCES} ${EXTERNAL_HEADERS}
- ${UNIT_TEST_FIXTURES}
- )
- target_link_libraries(nvim-test PRIVATE ${LUAJIT_LIBRARIES} main_lib PUBLIC libuv_lib)
- if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
- target_link_libraries(nvim-test PRIVATE "-framework CoreServices")
- endif()
- target_include_directories(nvim-test PRIVATE ${LUAJIT_INCLUDE_DIRS})
- set_target_properties(
- nvim-test
- PROPERTIES
- POSITION_INDEPENDENT_CODE ON
- )
- target_compile_definitions(nvim-test PRIVATE UNIT_TESTING)
-endif()
-
if(CLANG_ASAN_UBSAN)
message(STATUS "Enabling Clang address sanitizer and undefined behavior sanitizer for nvim.")
if(CI_BUILD)
@@ -977,7 +935,9 @@ add_glob_target(
TARGET lintc-clint
COMMAND ${PROJECT_SOURCE_DIR}/src/clint.py
FLAGS --output=${LINT_OUTPUT_FORMAT}
- FILES ${LINT_NVIM_SOURCES})
+ FILES ${LINT_NVIM_SOURCES}
+ EXCLUDE
+ tui/terminfo_defs.h)
add_custom_target(uncrustify-version
COMMAND ${CMAKE_COMMAND}
diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c
index 931363e199..a2cb297b15 100644
--- a/src/nvim/api/autocmd.c
+++ b/src/nvim/api/autocmd.c
@@ -404,7 +404,7 @@ cleanup:
/// - match: (string) expanded value of |<amatch>|
/// - buf: (number) expanded value of |<abuf>|
/// - file: (string) expanded value of |<afile>|
-/// - data: (any) arbitrary data passed to |nvim_exec_autocmds()|
+/// - data: (any) arbitrary data passed from |nvim_exec_autocmds()|
/// - command (string) optional: Vim command to execute on event. Cannot be used with
/// {callback}
/// - once (boolean) optional: defaults to false. Run the autocommand
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index 44e7ed3986..ab3b3485e4 100644
--- a/src/nvim/api/extmark.c
+++ b/src/nvim/api/extmark.c
@@ -698,7 +698,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
}
if (opts->sign_text.type == kObjectTypeString) {
- if (!init_sign_text((char **)&decor.sign_text,
+ if (!init_sign_text(&decor.sign_text,
opts->sign_text.data.string.data)) {
api_set_error(err, kErrorTypeValidation, "sign_text is not a valid value");
goto error;
diff --git a/src/nvim/api/keysets.lua b/src/nvim/api/keysets.lua
index 8f909e937f..30dcef6127 100644
--- a/src/nvim/api/keysets.lua
+++ b/src/nvim/api/keysets.lua
@@ -1,8 +1,8 @@
return {
- context = {
+ { 'context', {
"types";
- };
- set_decoration_provider = {
+ }};
+ { 'set_decoration_provider', {
"on_start";
"on_buf";
"on_win";
@@ -10,8 +10,8 @@ return {
"on_end";
"_on_hl_def";
"_on_spell_nav";
- };
- set_extmark = {
+ }};
+ { 'set_extmark', {
"id";
"end_line";
"end_row";
@@ -39,8 +39,8 @@ return {
"conceal";
"spell";
"ui_watched";
- };
- keymap = {
+ }};
+ { 'keymap', {
"noremap";
"nowait";
"silent";
@@ -50,11 +50,11 @@ return {
"callback";
"desc";
"replace_keycodes";
- };
- get_commands = {
+ }};
+ { 'get_commands', {
"builtin";
- };
- user_command = {
+ }};
+ { 'user_command', {
"addr";
"bang";
"bar";
@@ -67,8 +67,8 @@ return {
"preview";
"range";
"register";
- };
- float_config = {
+ }};
+ { 'float_config', {
"row";
"col";
"width";
@@ -85,25 +85,25 @@ return {
"title_pos";
"style";
"noautocmd";
- };
- runtime = {
+ }};
+ { 'runtime', {
"is_lua";
"do_source";
- };
- eval_statusline = {
+ }};
+ { 'eval_statusline', {
"winid";
"maxwidth";
"fillchar";
"highlights";
"use_winbar";
"use_tabline";
- };
- option = {
+ }};
+ { 'option', {
"scope";
"win";
"buf";
- };
- highlight = {
+ }};
+ { 'highlight', {
"bold";
"standout";
"strikethrough";
@@ -114,6 +114,7 @@ return {
"underdashed";
"italic";
"reverse";
+ "altfont";
"nocombine";
"default";
"cterm";
@@ -128,8 +129,8 @@ return {
"blend";
"fg_indexed";
"bg_indexed";
- };
- highlight_cterm = {
+ }};
+ { 'highlight_cterm', {
"bold";
"standout";
"strikethrough";
@@ -140,16 +141,17 @@ return {
"underdashed";
"italic";
"reverse";
+ "altfont";
"nocombine";
- };
+ }};
-- Autocmds
- clear_autocmds = {
+ { 'clear_autocmds', {
"buffer";
"event";
"group";
"pattern";
- };
- create_autocmd = {
+ }};
+ { 'create_autocmd', {
"buffer";
"callback";
"command";
@@ -158,24 +160,24 @@ return {
"nested";
"once";
"pattern";
- };
- exec_autocmds = {
+ }};
+ { 'exec_autocmds', {
"buffer";
"group";
"modeline";
"pattern";
"data";
- };
- get_autocmds = {
+ }};
+ { 'get_autocmds', {
"event";
"group";
"pattern";
"buffer";
- };
- create_augroup = {
+ }};
+ { 'create_augroup', {
"clear";
- };
- cmd = {
+ }};
+ { 'cmd', {
"cmd";
"range";
"count";
@@ -187,12 +189,12 @@ return {
"nargs";
"addr";
"nextcmd";
- };
- cmd_magic = {
+ }};
+ { 'cmd_magic', {
"file";
"bar";
- };
- cmd_mods = {
+ }};
+ { 'cmd_mods', {
"silent";
"emsg_silent";
"unsilent";
@@ -213,16 +215,15 @@ return {
"verbose";
"vertical";
"split";
- };
- cmd_mods_filter = {
+ }};
+ { 'cmd_mods_filter', {
"pattern";
"force";
- };
- cmd_opts = {
+ }};
+ { 'cmd_opts', {
"output";
- };
- echo_opts = {
+ }};
+ { 'echo_opts', {
"verbose";
- };
+ }};
}
-
diff --git a/src/nvim/api/private/converter.c b/src/nvim/api/private/converter.c
index 7770ba39d8..58ff552ab7 100644
--- a/src/nvim/api/private/converter.c
+++ b/src/nvim/api/private/converter.c
@@ -358,7 +358,7 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
}
case kObjectTypeLuaRef: {
- char *name = (char *)register_luafunc(api_new_luaref(obj.data.luaref));
+ char *name = register_luafunc(api_new_luaref(obj.data.luaref));
tv->v_type = VAR_FUNC;
tv->vval.v_string = xstrdup(name);
break;
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index 4ff600618d..519f2cc5bf 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -33,7 +33,6 @@
#include "nvim/pos.h"
#include "nvim/ui.h"
#include "nvim/version.h"
-#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/private/funcs_metadata.generated.h"
@@ -151,7 +150,18 @@ bool try_end(Error *err)
xfree(msg);
}
} else if (did_throw) {
- api_set_error(err, kErrorTypeException, "%s", current_exception->value);
+ if (*current_exception->throw_name != NUL) {
+ if (current_exception->throw_lnum != 0) {
+ api_set_error(err, kErrorTypeException, "%s, line %" PRIdLINENR ": %s",
+ current_exception->throw_name, current_exception->throw_lnum,
+ current_exception->value);
+ } else {
+ api_set_error(err, kErrorTypeException, "%s: %s",
+ current_exception->throw_name, current_exception->value);
+ }
+ } else {
+ api_set_error(err, kErrorTypeException, "%s", current_exception->value);
+ }
discard_current_exception();
}
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index 32b294c0ce..e67607a7e4 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -13,7 +13,11 @@
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/ui.h"
+#include "nvim/autocmd.h"
#include "nvim/channel.h"
+#include "nvim/event/loop.h"
+#include "nvim/event/wstream.h"
+#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/highlight.h"
#include "nvim/main.h"
@@ -27,13 +31,12 @@
#include "nvim/types.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
-#include "nvim/window.h"
#define BUF_POS(data) ((size_t)((data)->buf_wptr - (data)->buf))
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/ui.c.generated.h"
-# include "ui_events_remote.generated.h"
+# include "ui_events_remote.generated.h" // IWYU pragma: export
#endif
static PMap(uint64_t) connected_uis = MAP_INIT;
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 65b08ecade..a53b30dd8a 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -1834,7 +1834,7 @@ Dictionary nvim__stats(void)
/// - "width" Requested width of the UI
/// - "rgb" true if the UI uses RGB colors (false implies |cterm-colors|)
/// - "ext_..." Requested UI extensions, see |ui-option|
-/// - "chan" Channel id of remote UI or 0 for TUI
+/// - "chan" |channel-id| of remote UI
Array nvim_list_uis(void)
FUNC_API_SINCE(4)
{
@@ -2271,7 +2271,7 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
if (sp->userhl == 0) {
grpname = get_default_stl_hl(wp, use_winbar);
} else if (sp->userhl < 0) {
- grpname = (char *)syn_id2name(-sp->userhl);
+ grpname = syn_id2name(-sp->userhl);
} else {
snprintf(user_group, sizeof(user_group), "User%d", sp->userhl);
grpname = user_group;
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c
index f81d26b486..0ffeac1bff 100644
--- a/src/nvim/api/win_config.c
+++ b/src/nvim/api/win_config.c
@@ -278,7 +278,7 @@ Dictionary nvim_win_get_config(Window window, Error *err)
String s = cstrn_to_string((const char *)config->border_chars[i], sizeof(schar_T));
int hi_id = config->border_hl_ids[i];
- char *hi_name = (char *)syn_id2name(hi_id);
+ char *hi_name = syn_id2name(hi_id);
if (hi_name[0]) {
ADD(tuple, STRING_OBJ(s));
ADD(tuple, STRING_OBJ(cstr_to_string((const char *)hi_name)));
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index df8ad165ba..e2c234ab29 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -369,11 +369,16 @@ void nvim_win_hide(Window window, Error *err)
tabpage_T *tabpage = win_find_tabpage(win);
TryState tstate;
try_enter(&tstate);
- if (tabpage == curtab) {
+
+ // Never close the autocommand window.
+ if (is_aucmd_win(win)) {
+ emsg(_(e_autocmd_close));
+ } else if (tabpage == curtab) {
win_close(win, false, false);
} else {
win_close_othertab(win, false, tabpage);
}
+
vim_ignored = try_leave(&tstate, err);
}
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua
index 2c0cb771c3..a75ee3bbd5 100644
--- a/src/nvim/auevents.lua
+++ b/src/nvim/auevents.lua
@@ -127,10 +127,22 @@ return {
'WinScrolled', -- after a window was scrolled or resized
},
aliases = {
- BufCreate = 'BufAdd',
- BufRead = 'BufReadPost',
- BufWrite = 'BufWritePre',
- FileEncoding = 'EncodingChanged',
+ {
+ 'BufCreate',
+ 'BufAdd'
+ },
+ {
+ 'BufRead',
+ 'BufReadPost'
+ },
+ {
+ 'BufWrite',
+ 'BufWritePre'
+ },
+ {
+ 'FileEncoding',
+ 'EncodingChanged'
+ },
},
-- List of nvim-specific events or aliases for the purpose of generating
-- syntax file
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index cd1059eb0d..5dcb10751f 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -88,6 +88,7 @@
#include "nvim/regexp.h"
#include "nvim/runtime.h"
#include "nvim/screen.h"
+#include "nvim/search.h"
#include "nvim/sign.h"
#include "nvim/spell.h"
#include "nvim/statusline.h"
@@ -2254,12 +2255,13 @@ int buflist_findpat(const char *pattern, const char *pattern_end, bool unlisted,
regmatch_T regmatch;
regmatch.regprog = vim_regcomp(p, magic_isset() ? RE_MAGIC : 0);
- if (regmatch.regprog == NULL) {
- xfree(pat);
- return -1;
- }
FOR_ALL_BUFFERS_BACKWARDS(buf) {
+ if (regmatch.regprog == NULL) {
+ // invalid pattern, possibly after switching engine
+ xfree(pat);
+ return -1;
+ }
if (buf->b_p_bl == find_listed
&& (!diffmode || diff_mode_buf(buf))
&& buflist_match(&regmatch, buf, false) != NULL) {
@@ -2337,7 +2339,6 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options)
int round;
char *p;
int attempt;
- char *patc;
bufmatch_T *matches = NULL;
*num_file = 0; // return values in case of FAIL
@@ -2347,31 +2348,34 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options)
return FAIL;
}
- // Make a copy of "pat" and change "^" to "\(^\|[\/]\)".
- if (*pat == '^') {
- patc = xmalloc(strlen(pat) + 11);
- STRCPY(patc, "\\(^\\|[\\/]\\)");
- STRCPY(patc + 11, pat + 1);
- } else {
- patc = pat;
+ const bool fuzzy = cmdline_fuzzy_complete(pat);
+
+ char *patc = NULL;
+ // Make a copy of "pat" and change "^" to "\(^\|[\/]\)" (if doing regular
+ // expression matching)
+ if (!fuzzy) {
+ if (*pat == '^') {
+ patc = xmalloc(strlen(pat) + 11);
+ STRCPY(patc, "\\(^\\|[\\/]\\)");
+ STRCPY(patc + 11, pat + 1);
+ } else {
+ patc = pat;
+ }
}
+ fuzmatch_str_T *fuzmatch = NULL;
// attempt == 0: try match with '\<', match at start of word
// attempt == 1: try match without '\<', match anywhere
- for (attempt = 0; attempt <= 1; attempt++) {
- if (attempt > 0 && patc == pat) {
- break; // there was no anchor, no need to try again
- }
-
+ for (attempt = 0; attempt <= (fuzzy ? 0 : 1); attempt++) {
regmatch_T regmatch;
- regmatch.regprog = vim_regcomp(patc + attempt * 11, RE_MAGIC);
- if (regmatch.regprog == NULL) {
- if (patc != pat) {
- xfree(patc);
+ if (!fuzzy) {
+ if (attempt > 0 && patc == pat) {
+ break; // there was no anchor, no need to try again
}
- return FAIL;
+ regmatch.regprog = vim_regcomp(patc + attempt * 11, RE_MAGIC);
}
+ int score = 0;
// round == 1: Count the matches.
// round == 2: Build the array to keep the matches.
for (round = 1; round <= 2; round++) {
@@ -2387,64 +2391,108 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options)
continue;
}
}
- p = buflist_match(&regmatch, buf, p_wic);
- if (p != NULL) {
- if (round == 1) {
- count++;
- } else {
- if (options & WILD_HOME_REPLACE) {
- p = home_replace_save(buf, p);
- } else {
- p = xstrdup(p);
+
+ if (!fuzzy) {
+ if (regmatch.regprog == NULL) {
+ // invalid pattern, possibly after recompiling
+ if (patc != pat) {
+ xfree(patc);
}
- if (matches != NULL) {
- matches[count].buf = buf;
- matches[count].match = p;
- count++;
- } else {
- (*file)[count++] = p;
+ return FAIL;
+ }
+ p = buflist_match(&regmatch, buf, p_wic);
+ } else {
+ p = NULL;
+ // first try matching with the short file name
+ if ((score = fuzzy_match_str(buf->b_sfname, pat)) != 0) {
+ p = buf->b_sfname;
+ }
+ if (p == NULL) {
+ // next try matching with the full path file name
+ if ((score = fuzzy_match_str(buf->b_ffname, pat)) != 0) {
+ p = buf->b_ffname;
}
}
}
+
+ if (p == NULL) {
+ continue;
+ }
+
+ if (round == 1) {
+ count++;
+ continue;
+ }
+
+ if (options & WILD_HOME_REPLACE) {
+ p = home_replace_save(buf, p);
+ } else {
+ p = xstrdup(p);
+ }
+
+ if (!fuzzy) {
+ if (matches != NULL) {
+ matches[count].buf = buf;
+ matches[count].match = p;
+ count++;
+ } else {
+ (*file)[count++] = p;
+ }
+ } else {
+ fuzmatch[count].idx = count;
+ fuzmatch[count].str = p;
+ fuzmatch[count].score = score;
+ count++;
+ }
}
if (count == 0) { // no match found, break here
break;
}
if (round == 1) {
- *file = xmalloc((size_t)count * sizeof(**file));
-
- if (options & WILD_BUFLASTUSED) {
- matches = xmalloc((size_t)count * sizeof(*matches));
+ if (!fuzzy) {
+ *file = xmalloc((size_t)count * sizeof(**file));
+ if (options & WILD_BUFLASTUSED) {
+ matches = xmalloc((size_t)count * sizeof(*matches));
+ }
+ } else {
+ fuzmatch = xmalloc((size_t)count * sizeof(fuzmatch_str_T));
}
}
}
- vim_regfree(regmatch.regprog);
- if (count) { // match(es) found, break here
- break;
+
+ if (!fuzzy) {
+ vim_regfree(regmatch.regprog);
+ if (count) { // match(es) found, break here
+ break;
+ }
}
}
- if (patc != pat) {
+ if (!fuzzy && patc != pat) {
xfree(patc);
}
- if (matches != NULL) {
- if (count > 1) {
- qsort(matches, (size_t)count, sizeof(bufmatch_T), buf_time_compare);
- }
-
- // if the current buffer is first in the list, place it at the end
- if (matches[0].buf == curbuf) {
- for (int i = 1; i < count; i++) {
- (*file)[i - 1] = matches[i].match;
+ if (!fuzzy) {
+ if (matches != NULL) {
+ if (count > 1) {
+ qsort(matches, (size_t)count, sizeof(bufmatch_T), buf_time_compare);
}
- (*file)[count - 1] = matches[0].match;
- } else {
- for (int i = 0; i < count; i++) {
- (*file)[i] = matches[i].match;
+
+ // if the current buffer is first in the list, place it at the end
+ if (matches[0].buf == curbuf) {
+ for (int i = 1; i < count; i++) {
+ (*file)[i - 1] = matches[i].match;
+ }
+ (*file)[count - 1] = matches[0].match;
+ } else {
+ for (int i = 0; i < count; i++) {
+ (*file)[i] = matches[i].match;
+ }
}
+ xfree(matches);
}
- xfree(matches);
+ } else {
+ fuzzymatches_to_strmatches(fuzmatch, file, count, false);
}
*num_file = count;
@@ -2452,6 +2500,7 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options)
}
/// Check for a match on the file name for buffer "buf" with regprog "prog".
+/// Note that rmp->regprog may become NULL when switching regexp engine.
///
/// @param ignore_case When true, ignore case. Use 'fic' otherwise.
static char *buflist_match(regmatch_T *rmp, buf_T *buf, bool ignore_case)
@@ -2464,7 +2513,8 @@ static char *buflist_match(regmatch_T *rmp, buf_T *buf, bool ignore_case)
return match;
}
-/// Try matching the regexp in "prog" with file name "name".
+/// Try matching the regexp in "rmp->regprog" with file name "name".
+/// Note that rmp->regprog may become NULL when switching regexp engine.
///
/// @param ignore_case When true, ignore case. Use 'fileignorecase' otherwise.
///
@@ -3293,7 +3343,7 @@ void maketitle(void)
(SPACE_FOR_DIR - (size_t)(buf_p - buf)), true);
#ifdef BACKSLASH_IN_FILENAME
// Avoid "c:/name" to be reduced to "c".
- if (isalpha((uint8_t)buf_p) && *(buf_p + 1) == ':') {
+ if (isalpha((uint8_t)(*buf_p)) && *(buf_p + 1) == ':') {
buf_p += 2;
}
#endif
@@ -3779,7 +3829,7 @@ static int chk_modeline(linenr_T lnum, int flags)
&& (s[0] != 'V'
|| strncmp(skipwhite(e + 1), "set", 3) == 0)
&& (s[3] == ':'
- || (VIM_VERSION_100 >= vers && isdigit(s[3]))
+ || (VIM_VERSION_100 >= vers && isdigit((uint8_t)s[3]))
|| (VIM_VERSION_100 < vers && s[3] == '<')
|| (VIM_VERSION_100 > vers && s[3] == '>')
|| (VIM_VERSION_100 == vers && s[3] == '='))) {
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index f01edd1ad2..4c99191170 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -1392,6 +1392,7 @@ struct window_S {
int w_prev_fraction_row;
linenr_T w_nrwidth_line_count; // line count when ml_nrwidth_width was computed.
+ linenr_T w_statuscol_line_count; // line count when 'statuscolumn' width was computed.
int w_nrwidth_width; // nr of chars to print line count.
qf_info_T *w_llist; // Location list for this window
diff --git a/src/nvim/change.c b/src/nvim/change.c
index e8c4af9879..06696610b0 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -418,14 +418,7 @@ void appended_lines(linenr_T lnum, linenr_T count)
/// Like appended_lines(), but adjust marks first.
void appended_lines_mark(linenr_T lnum, long count)
{
- // Skip mark_adjust when adding a line after the last one, there can't
- // be marks there. But it's still needed in diff mode.
- if (lnum + count < curbuf->b_ml.ml_line_count || curwin->w_p_diff) {
- mark_adjust(lnum + 1, (linenr_T)MAXLNUM, (linenr_T)count, 0L, kExtmarkUndo);
- } else {
- extmark_adjust(curbuf, lnum + 1, (linenr_T)MAXLNUM, (linenr_T)count, 0L,
- kExtmarkUndo);
- }
+ mark_adjust(lnum + 1, (linenr_T)MAXLNUM, (linenr_T)count, 0L, kExtmarkUndo);
changed_lines(lnum + 1, 0, lnum + 1, (linenr_T)count, true);
}
@@ -1694,13 +1687,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
}
// Postpone calling changed_lines(), because it would mess up folding
// with markers.
- // Skip mark_adjust when adding a line after the last one, there can't
- // be marks there. But still needed in diff mode.
- if (curwin->w_cursor.lnum + 1 < curbuf->b_ml.ml_line_count
- || curwin->w_p_diff) {
- mark_adjust(curwin->w_cursor.lnum + 1, (linenr_T)MAXLNUM, 1L, 0L,
- kExtmarkNOOP);
- }
+ mark_adjust(curwin->w_cursor.lnum + 1, (linenr_T)MAXLNUM, 1L, 0L, kExtmarkNOOP);
did_append = true;
} else {
// In MODE_VREPLACE state we are starting to replace the next line.
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index 4115743e1c..5aec9ccf9d 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -13,6 +13,7 @@
#include <string.h>
#include "auto/config.h"
+#include "klib/kvec.h"
#include "nvim/ascii.h"
#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
@@ -35,6 +36,7 @@
#include "nvim/plines.h"
#include "nvim/pos.h"
#include "nvim/state.h"
+#include "nvim/strings.h"
#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -144,19 +146,19 @@ int buf_init_chartab(buf_T *buf, int global)
// options Each option is a list of characters, character numbers or
// ranges, separated by commas, e.g.: "200-210,x,#-178,-"
for (i = global ? 0 : 3; i <= 3; i++) {
- const char_u *p;
+ const char *p;
if (i == 0) {
// first round: 'isident'
- p = (char_u *)p_isi;
+ p = p_isi;
} else if (i == 1) {
// second round: 'isprint'
- p = (char_u *)p_isp;
+ p = p_isp;
} else if (i == 2) {
// third round: 'isfname'
- p = (char_u *)p_isf;
+ p = p_isf;
} else { // i == 3
// fourth round: 'iskeyword'
- p = (char_u *)buf->b_p_isk;
+ p = buf->b_p_isk;
}
while (*p) {
@@ -252,8 +254,8 @@ int buf_init_chartab(buf_T *buf, int global)
c++;
}
- c = *p;
- p = (char_u *)skip_to_option_part((char *)p);
+ c = (uint8_t)(*p);
+ p = skip_to_option_part(p);
if ((c == ',') && (*p == NUL)) {
// Trailing comma is not allowed.
@@ -538,9 +540,9 @@ static char_u transchar_charbuf[11];
/// @param[in] c Character to translate.
///
/// @return translated character into a static buffer.
-char_u *transchar(int c)
+char *transchar(int c)
{
- return transchar_buf(curbuf, c);
+ return (char *)transchar_buf(curbuf, c);
}
char_u *transchar_buf(const buf_T *buf, int c)
@@ -582,7 +584,7 @@ char_u *transchar_byte(const int c)
transchar_nonprint(curbuf, transchar_charbuf, c);
return transchar_charbuf;
}
- return transchar(c);
+ return (char_u *)transchar(c);
}
/// Convert non-printable characters to 2..4 printable ones
diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c
index b5ec3e7032..5e4b49db24 100644
--- a/src/nvim/cmdexpand.c
+++ b/src/nvim/cmdexpand.c
@@ -89,9 +89,42 @@ static int compl_match_arraysize;
static int compl_startcol;
static int compl_selected;
-#define SHOW_FILE_TEXT(m) (showtail \
- ? showmatches_gettail(matches[m], false) \
- : matches[m])
+#define SHOW_MATCH(m) (showtail ? showmatches_gettail(matches[m], false) : matches[m])
+
+/// Returns true if fuzzy completion is supported for a given cmdline completion
+/// context.
+static bool cmdline_fuzzy_completion_supported(const expand_T *const xp)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
+{
+ return (wop_flags & WOP_FUZZY)
+ && xp->xp_context != EXPAND_BOOL_SETTINGS
+ && xp->xp_context != EXPAND_COLORS
+ && xp->xp_context != EXPAND_COMPILER
+ && xp->xp_context != EXPAND_DIRECTORIES
+ && xp->xp_context != EXPAND_FILES
+ && xp->xp_context != EXPAND_FILES_IN_PATH
+ && xp->xp_context != EXPAND_FILETYPE
+ && xp->xp_context != EXPAND_HELP
+ && xp->xp_context != EXPAND_LUA
+ && xp->xp_context != EXPAND_OLD_SETTING
+ && xp->xp_context != EXPAND_OWNSYNTAX
+ && xp->xp_context != EXPAND_PACKADD
+ && xp->xp_context != EXPAND_RUNTIME
+ && xp->xp_context != EXPAND_SHELLCMD
+ && xp->xp_context != EXPAND_TAGS
+ && xp->xp_context != EXPAND_TAGS_LISTFILES
+ && xp->xp_context != EXPAND_USER_LIST
+ && xp->xp_context != EXPAND_USER_LUA;
+}
+
+/// Returns true if fuzzy completion for cmdline completion is enabled and
+/// "fuzzystr" is not empty. If search pattern is empty, then don't use fuzzy
+/// matching.
+bool cmdline_fuzzy_complete(const char *const fuzzystr)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
+{
+ return (wop_flags & WOP_FUZZY) && *fuzzystr != NUL;
+}
/// Sort function for the completion matches.
/// <SNR> functions should be sorted to the end.
@@ -110,71 +143,75 @@ static int sort_func_compare(const void *s1, const void *s2)
}
/// Escape special characters in the cmdline completion matches.
-static void ExpandEscape(expand_T *xp, char *str, int numfiles, char **files, int options)
+static void wildescape(expand_T *xp, const char *str, int numfiles, char **files)
{
- int i;
char *p;
const int vse_what = xp->xp_context == EXPAND_BUFFERS ? VSE_BUFFER : VSE_NONE;
- // May change home directory back to "~"
- if (options & WILD_HOME_REPLACE) {
- tilde_replace(str, numfiles, files);
- }
-
- if (options & WILD_ESCAPE) {
- if (xp->xp_context == EXPAND_FILES
- || xp->xp_context == EXPAND_FILES_IN_PATH
- || xp->xp_context == EXPAND_SHELLCMD
- || xp->xp_context == EXPAND_BUFFERS
- || xp->xp_context == EXPAND_DIRECTORIES) {
- // Insert a backslash into a file name before a space, \, %, #
- // and wildmatch characters, except '~'.
- for (i = 0; i < numfiles; i++) {
- // for ":set path=" we need to escape spaces twice
- if (xp->xp_backslash == XP_BS_THREE) {
- p = vim_strsave_escaped(files[i], " ");
- xfree(files[i]);
- files[i] = p;
+ if (xp->xp_context == EXPAND_FILES
+ || xp->xp_context == EXPAND_FILES_IN_PATH
+ || xp->xp_context == EXPAND_SHELLCMD
+ || xp->xp_context == EXPAND_BUFFERS
+ || xp->xp_context == EXPAND_DIRECTORIES) {
+ // Insert a backslash into a file name before a space, \, %, #
+ // and wildmatch characters, except '~'.
+ for (int i = 0; i < numfiles; i++) {
+ // for ":set path=" we need to escape spaces twice
+ if (xp->xp_backslash == XP_BS_THREE) {
+ p = vim_strsave_escaped(files[i], " ");
+ xfree(files[i]);
+ files[i] = p;
#if defined(BACKSLASH_IN_FILENAME)
- p = vim_strsave_escaped(files[i], (char_u *)" ");
- xfree(files[i]);
- files[i] = p;
+ p = vim_strsave_escaped(files[i], " ");
+ xfree(files[i]);
+ files[i] = p;
#endif
- }
+ }
#ifdef BACKSLASH_IN_FILENAME
- p = vim_strsave_fnameescape((const char *)files[i], vse_what);
+ p = vim_strsave_fnameescape(files[i], vse_what);
#else
- p = vim_strsave_fnameescape((const char *)files[i],
- xp->xp_shell ? VSE_SHELL : vse_what);
+ p = vim_strsave_fnameescape(files[i], xp->xp_shell ? VSE_SHELL : vse_what);
#endif
- xfree(files[i]);
- files[i] = p;
+ xfree(files[i]);
+ files[i] = p;
- // If 'str' starts with "\~", replace "~" at start of
- // files[i] with "\~".
- if (str[0] == '\\' && str[1] == '~' && files[i][0] == '~') {
- escape_fname(&files[i]);
- }
+ // If 'str' starts with "\~", replace "~" at start of
+ // files[i] with "\~".
+ if (str[0] == '\\' && str[1] == '~' && files[i][0] == '~') {
+ escape_fname(&files[i]);
}
- xp->xp_backslash = XP_BS_NONE;
+ }
+ xp->xp_backslash = XP_BS_NONE;
- // If the first file starts with a '+' escape it. Otherwise it
- // could be seen as "+cmd".
- if (*files[0] == '+') {
- escape_fname(&files[0]);
- }
- } else if (xp->xp_context == EXPAND_TAGS) {
- // Insert a backslash before characters in a tag name that
- // would terminate the ":tag" command.
- for (i = 0; i < numfiles; i++) {
- p = vim_strsave_escaped(files[i], "\\|\"");
- xfree(files[i]);
- files[i] = p;
- }
+ // If the first file starts with a '+' escape it. Otherwise it
+ // could be seen as "+cmd".
+ if (*files[0] == '+') {
+ escape_fname(&files[0]);
+ }
+ } else if (xp->xp_context == EXPAND_TAGS) {
+ // Insert a backslash before characters in a tag name that
+ // would terminate the ":tag" command.
+ for (int i = 0; i < numfiles; i++) {
+ p = vim_strsave_escaped(files[i], "\\|\"");
+ xfree(files[i]);
+ files[i] = p;
}
}
}
+/// Escape special characters in the cmdline completion matches.
+static void ExpandEscape(expand_T *xp, char *str, int numfiles, char **files, int options)
+{
+ // May change home directory back to "~"
+ if (options & WILD_HOME_REPLACE) {
+ tilde_replace(str, numfiles, files);
+ }
+
+ if (options & WILD_ESCAPE) {
+ wildescape(xp, str, numfiles, files);
+ }
+}
+
/// Return FAIL if this is not an appropriate context in which to do
/// completion of anything, return OK if it is (even if there are no matches).
/// For the caller, this means that the character is just passed through like a
@@ -215,12 +252,19 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
assert(ccline->cmdpos >= i);
xp->xp_pattern_len = (size_t)ccline->cmdpos - (size_t)i;
- if (type == WILD_NEXT || type == WILD_PREV || type == WILD_PUM_WANT) {
+ if (type == WILD_NEXT || type == WILD_PREV
+ || type == WILD_PAGEUP || type == WILD_PAGEDOWN
+ || type == WILD_PUM_WANT) {
// Get next/previous match for a previous expanded pattern.
p2 = ExpandOne(xp, NULL, NULL, 0, type);
} else {
+ if (cmdline_fuzzy_completion_supported(xp)) {
+ // If fuzzy matching, don't modify the search string
+ p1 = xstrdup(xp->xp_pattern);
+ } else {
+ p1 = addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context);
+ }
// Translate string into pattern and expand it.
- p1 = addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context);
const int use_options = (options
| WILD_HOME_REPLACE
| WILD_ADD_SLASH
@@ -296,7 +340,7 @@ static int cmdline_pum_create(CmdlineInfo *ccline, expand_T *xp, char **matches,
compl_match_array = xmalloc(sizeof(pumitem_T) * (size_t)compl_match_arraysize);
for (int i = 0; i < numMatches; i++) {
compl_match_array[i] = (pumitem_T){
- .pum_text = SHOW_FILE_TEXT(i),
+ .pum_text = SHOW_MATCH(i),
.pum_info = NULL,
.pum_extra = NULL,
.pum_kind = NULL,
@@ -397,7 +441,6 @@ static int wildmenu_match_len(expand_T *xp, char *s)
/// @param matches list of matches
static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int match, int showtail)
{
-#define L_MATCH(m) (showtail ? showmatches_gettail(matches[m], false) : matches[m])
int row;
char *buf;
int len;
@@ -426,7 +469,7 @@ static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int m
highlight = false;
}
// count 1 for the ending ">"
- clen = wildmenu_match_len(xp, L_MATCH(match)) + 3;
+ clen = wildmenu_match_len(xp, SHOW_MATCH(match)) + 3;
if (match == 0) {
first_match = 0;
} else if (match < first_match) {
@@ -436,7 +479,7 @@ static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int m
} else {
// check if match fits on the screen
for (i = first_match; i < match; i++) {
- clen += wildmenu_match_len(xp, L_MATCH(i)) + 2;
+ clen += wildmenu_match_len(xp, SHOW_MATCH(i)) + 2;
}
if (first_match > 0) {
clen += 2;
@@ -447,7 +490,7 @@ static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int m
// if showing the last match, we can add some on the left
clen = 2;
for (i = match; i < num_matches; i++) {
- clen += wildmenu_match_len(xp, L_MATCH(i)) + 2;
+ clen += wildmenu_match_len(xp, SHOW_MATCH(i)) + 2;
if ((long)clen >= Columns) {
break;
}
@@ -459,7 +502,7 @@ static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int m
}
if (add_left) {
while (first_match > 0) {
- clen += wildmenu_match_len(xp, L_MATCH(first_match - 1)) + 2;
+ clen += wildmenu_match_len(xp, SHOW_MATCH(first_match - 1)) + 2;
if ((long)clen >= Columns) {
break;
}
@@ -479,13 +522,13 @@ static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int m
clen = len;
i = first_match;
- while (clen + wildmenu_match_len(xp, L_MATCH(i)) + 2 < Columns) {
+ while (clen + wildmenu_match_len(xp, SHOW_MATCH(i)) + 2 < Columns) {
if (i == match) {
selstart = buf + len;
selstart_col = clen;
}
- s = L_MATCH(i);
+ s = SHOW_MATCH(i);
// Check for menu separators - replace with '|'
emenu = (xp->xp_context == EXPAND_MENUS
|| xp->xp_context == EXPAND_MENUNAMES);
@@ -592,6 +635,44 @@ static char *get_next_or_prev_match(int mode, expand_T *xp, int *p_findex, char
findex--;
} else if (mode == WILD_NEXT) {
findex++;
+ } else if (mode == WILD_PAGEUP) {
+ if (findex == 0) {
+ // at the first entry, don't select any entries
+ findex = -1;
+ } else if (findex == -1) {
+ // no entry is selected. select the last entry
+ findex = xp->xp_numfiles - 1;
+ } else {
+ // go up by the pum height
+ int ht = pum_get_height();
+ if (ht > 3) {
+ ht -= 2;
+ }
+ findex -= ht;
+ if (findex < 0) {
+ // few entries left, select the first entry
+ findex = 0;
+ }
+ }
+ } else if (mode == WILD_PAGEDOWN) {
+ if (findex == xp->xp_numfiles - 1) {
+ // at the last entry, don't select any entries
+ findex = -1;
+ } else if (findex == -1) {
+ // no entry is selected. select the first entry
+ findex = 0;
+ } else {
+ // go down by the pum height
+ int ht = pum_get_height();
+ if (ht > 3) {
+ ht -= 2;
+ }
+ findex += ht;
+ if (findex >= xp->xp_numfiles) {
+ // few entries left, select the last entry
+ findex = xp->xp_numfiles - 1;
+ }
+ }
} else { // mode == WILD_PUM_WANT
assert(pum_want.active);
findex = pum_want.item;
@@ -769,7 +850,9 @@ char *ExpandOne(expand_T *xp, char *str, char *orig, int options, int mode)
int i;
// first handle the case of using an old match
- if (mode == WILD_NEXT || mode == WILD_PREV || mode == WILD_PUM_WANT) {
+ if (mode == WILD_NEXT || mode == WILD_PREV
+ || mode == WILD_PAGEUP || mode == WILD_PAGEDOWN
+ || mode == WILD_PUM_WANT) {
return get_next_or_prev_match(mode, xp, &findex, orig_save);
}
@@ -897,7 +980,7 @@ static void showmatches_oneline(expand_T *xp, char **matches, int numMatches, in
// Expansion was done before and special characters
// were escaped, need to halve backslashes. Also
// $HOME has been replaced with ~/.
- char *exp_path = (char *)expand_env_save_opt(matches[j], true);
+ char *exp_path = expand_env_save_opt(matches[j], true);
char *path = exp_path != NULL ? exp_path : matches[j];
char *halved_slash = backslash_halve_save(path);
isdir = os_isdir(halved_slash);
@@ -910,14 +993,14 @@ static void showmatches_oneline(expand_T *xp, char **matches, int numMatches, in
isdir = os_isdir(matches[j]);
}
if (showtail) {
- p = SHOW_FILE_TEXT(j);
+ p = SHOW_MATCH(j);
} else {
home_replace(NULL, matches[j], NameBuff, MAXPATHL, true);
p = NameBuff;
}
} else {
isdir = false;
- p = SHOW_FILE_TEXT(j);
+ p = SHOW_MATCH(j);
}
lastlen = msg_outtrans_attr(p, isdir ? dir_attr : 0);
}
@@ -990,7 +1073,7 @@ int showmatches(expand_T *xp, int wildmenu)
home_replace(NULL, matches[i], NameBuff, MAXPATHL, true);
j = vim_strsize(NameBuff);
} else {
- j = vim_strsize(SHOW_FILE_TEXT(i));
+ j = vim_strsize(SHOW_MATCH(i));
}
if (j > maxlen) {
maxlen = j;
@@ -1092,7 +1175,7 @@ static bool expand_showtail(expand_T *xp)
// separator, on DOS the '*' "path\*\file" must not be skipped.
if (rem_backslash(s)) {
s++;
- } else if (vim_strchr("*?[", *s) != NULL) {
+ } else if (vim_strchr("*?[", (uint8_t)(*s)) != NULL) {
return false;
}
}
@@ -1133,6 +1216,7 @@ char *addstar(char *fname, size_t len, int context)
|| context == EXPAND_OWNSYNTAX
|| context == EXPAND_FILETYPE
|| context == EXPAND_PACKADD
+ || context == EXPAND_RUNTIME
|| ((context == EXPAND_TAGS_LISTFILES || context == EXPAND_TAGS)
&& fname[0] == '/')) {
retval = xstrnsave(fname, len);
@@ -1292,13 +1376,16 @@ static const char *set_cmd_index(const char *cmd, exarg_T *eap, expand_T *xp, in
{
const char *p = NULL;
size_t len = 0;
+ const bool fuzzy = cmdline_fuzzy_complete(cmd);
// Isolate the command and search for it in the command table.
// Exceptions:
- // - the 'k' command can directly be followed by any character, but
- // do accept "keepmarks", "keepalt" and "keepjumps".
+ // - the 'k' command can directly be followed by any character, but do
+ // accept "keepmarks", "keepalt" and "keepjumps". As fuzzy matching can
+ // find matches anywhere in the command name, do this only for command
+ // expansion based on regular expression and not for fuzzy matching.
// - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
- if (*cmd == 'k' && cmd[1] != 'e') {
+ if (!fuzzy && (*cmd == 'k' && cmd[1] != 'e')) {
eap->cmdidx = CMD_k;
p = cmd + 1;
} else {
@@ -1320,7 +1407,7 @@ static const char *set_cmd_index(const char *cmd, exarg_T *eap, expand_T *xp, in
}
}
// check for non-alpha command
- if (p == cmd && vim_strchr("@*!=><&~#", *p) != NULL) {
+ if (p == cmd && vim_strchr("@*!=><&~#", (uint8_t)(*p)) != NULL) {
p++;
}
len = (size_t)(p - cmd);
@@ -1332,7 +1419,11 @@ static const char *set_cmd_index(const char *cmd, exarg_T *eap, expand_T *xp, in
eap->cmdidx = excmd_get_cmdidx(cmd, len);
- if (cmd[0] >= 'A' && cmd[0] <= 'Z') {
+ // User defined commands support alphanumeric characters.
+ // Also when doing fuzzy expansion for non-shell commands, support
+ // alphanumeric characters.
+ if ((cmd[0] >= 'A' && cmd[0] <= 'Z')
+ || (fuzzy && eap->cmdidx != CMD_bang && *p != NUL)) {
while (ASCII_ISALNUM(*p) || *p == '*') { // Allow * wild card
p++;
}
@@ -1346,7 +1437,7 @@ static const char *set_cmd_index(const char *cmd, exarg_T *eap, expand_T *xp, in
}
if (eap->cmdidx == CMD_SIZE) {
- if (*cmd == 's' && vim_strchr("cgriI", cmd[1]) != NULL) {
+ if (*cmd == 's' && vim_strchr("cgriI", (uint8_t)cmd[1]) != NULL) {
eap->cmdidx = CMD_substitute;
p = cmd + 1;
} else if (cmd[0] >= 'A' && cmd[0] <= 'Z') {
@@ -1615,6 +1706,78 @@ static const char *set_context_in_lang_cmd(expand_T *xp, const char *arg)
return NULL;
}
+static enum {
+ EXP_BREAKPT_ADD, ///< expand ":breakadd" sub-commands
+ EXP_BREAKPT_DEL, ///< expand ":breakdel" sub-commands
+ EXP_PROFDEL, ///< expand ":profdel" sub-commands
+} breakpt_expand_what;
+
+/// Set the completion context for the :breakadd command. Always returns NULL.
+static const char *set_context_in_breakadd_cmd(expand_T *xp, const char *arg, cmdidx_T cmdidx)
+{
+ xp->xp_context = EXPAND_BREAKPOINT;
+ xp->xp_pattern = (char *)arg;
+
+ if (cmdidx == CMD_breakadd) {
+ breakpt_expand_what = EXP_BREAKPT_ADD;
+ } else if (cmdidx == CMD_breakdel) {
+ breakpt_expand_what = EXP_BREAKPT_DEL;
+ } else {
+ breakpt_expand_what = EXP_PROFDEL;
+ }
+
+ const char *p = skipwhite(arg);
+ if (*p == NUL) {
+ return NULL;
+ }
+ const char *subcmd_start = p;
+
+ if (strncmp("file ", p, 5) == 0 || strncmp("func ", p, 5) == 0) {
+ // :breakadd file [lnum] <filename>
+ // :breakadd func [lnum] <funcname>
+ p += 4;
+ p = skipwhite(p);
+
+ // skip line number (if specified)
+ if (ascii_isdigit(*p)) {
+ p = skipdigits(p);
+ if (*p != ' ') {
+ xp->xp_context = EXPAND_NOTHING;
+ return NULL;
+ }
+ p = skipwhite(p);
+ }
+ if (strncmp("file", subcmd_start, 4) == 0) {
+ xp->xp_context = EXPAND_FILES;
+ } else {
+ xp->xp_context = EXPAND_USER_FUNC;
+ }
+ xp->xp_pattern = (char *)p;
+ } else if (strncmp("expr ", p, 5) == 0) {
+ // :breakadd expr <expression>
+ xp->xp_context = EXPAND_EXPRESSION;
+ xp->xp_pattern = skipwhite(p + 5);
+ }
+
+ return NULL;
+}
+
+static const char *set_context_in_scriptnames_cmd(expand_T *xp, const char *arg)
+{
+ xp->xp_context = EXPAND_NOTHING;
+ xp->xp_pattern = NULL;
+
+ char *p = skipwhite(arg);
+ if (ascii_isdigit(*p)) {
+ return NULL;
+ }
+
+ xp->xp_context = EXPAND_SCRIPTNAMES;
+ xp->xp_pattern = p;
+
+ return NULL;
+}
+
/// Set the completion context in "xp" for command "cmd" with index "cmdidx".
/// The argument to the command is "arg" and the argument flags is "argt".
/// For user-defined commands and for environment variables, "context" has the
@@ -1931,6 +2094,10 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, expa
xp->xp_pattern = (char *)arg;
break;
+ case CMD_runtime:
+ set_context_in_runtime_cmd(xp, arg);
+ break;
+
#ifdef HAVE_WORKING_LIBINTL
case CMD_language:
return set_context_in_lang_cmd(xp, arg);
@@ -1969,6 +2136,14 @@ static const char *set_context_by_cmdname(const char *cmd, cmdidx_T cmdidx, expa
xp->xp_pattern = (char *)arg;
break;
+ case CMD_breakadd:
+ case CMD_profdel:
+ case CMD_breakdel:
+ return set_context_in_breakadd_cmd(xp, arg, cmdidx);
+
+ case CMD_scriptnames:
+ return set_context_in_scriptnames_cmd(xp, arg);
+
case CMD_lua:
xp->xp_context = EXPAND_LUA;
break;
@@ -2002,7 +2177,7 @@ static const char *set_one_cmd_context(expand_T *xp, const char *buff)
// 1. skip comment lines and leading space, colons or bars
const char *cmd;
- for (cmd = buff; vim_strchr(" \t:|", *cmd) != NULL; cmd++) {}
+ for (cmd = buff; vim_strchr(" \t:|", (uint8_t)(*cmd)) != NULL; cmd++) {}
xp->xp_pattern = (char *)cmd;
if (*cmd == NUL) {
@@ -2180,7 +2355,7 @@ void set_cmd_context(expand_T *xp, char *str, int len, int col, int use_ccline)
} else if (use_ccline && ccline->input_fn) {
xp->xp_context = ccline->xp_context;
xp->xp_pattern = ccline->cmdbuff;
- xp->xp_arg = (char *)ccline->xp_arg;
+ xp->xp_arg = ccline->xp_arg;
} else {
while (nextcomm != NULL) {
nextcomm = set_one_cmd_context(xp, nextcomm);
@@ -2226,7 +2401,12 @@ int expand_cmdline(expand_T *xp, const char *str, int col, int *matchcount, char
// add star to file name, or convert to regexp if not exp. files.
assert((str + col) - xp->xp_pattern >= 0);
xp->xp_pattern_len = (size_t)((str + col) - xp->xp_pattern);
- file_str = addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context);
+ if (cmdline_fuzzy_completion_supported(xp)) {
+ // If fuzzy matching, don't modify the search string
+ file_str = xstrdup(xp->xp_pattern);
+ } else {
+ file_str = addstar(xp->xp_pattern, xp->xp_pattern_len, xp->xp_context);
+ }
if (p_wic) {
options += WILD_ICASE;
@@ -2316,6 +2496,45 @@ static char *get_behave_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
}
/// Function given to ExpandGeneric() to obtain the possible arguments of the
+/// ":breakadd {expr, file, func, here}" command.
+/// ":breakdel {func, file, here}" command.
+static char *get_breakadd_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
+{
+ char *opts[] = { "expr", "file", "func", "here" };
+
+ if (idx >= 0 && idx <= 3) {
+ // breakadd {expr, file, func, here}
+ if (breakpt_expand_what == EXP_BREAKPT_ADD) {
+ return opts[idx];
+ } else if (breakpt_expand_what == EXP_BREAKPT_DEL) {
+ // breakdel {func, file, here}
+ if (idx <= 2) {
+ return opts[idx + 1];
+ }
+ } else {
+ // profdel {func, file}
+ if (idx <= 1) {
+ return opts[idx + 1];
+ }
+ }
+ }
+ return NULL;
+}
+
+/// Function given to ExpandGeneric() to obtain the possible arguments for the
+/// ":scriptnames" command.
+static char *get_scriptnames_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
+{
+ if (!SCRIPT_ID_VALID(idx + 1)) {
+ return NULL;
+ }
+
+ scriptitem_T *si = &SCRIPT_ITEM(idx + 1);
+ home_replace(NULL, si->sn_name, NameBuff, MAXPATHL, true);
+ return NameBuff;
+}
+
+/// Function given to ExpandGeneric() to obtain the possible arguments of the
/// ":messages {clear}" command.
static char *get_messages_arg(expand_T *xp FUNC_ATTR_UNUSED, int idx)
{
@@ -2360,7 +2579,7 @@ static char *get_healthcheck_names(expand_T *xp FUNC_ATTR_UNUSED, int idx)
}
/// Do the expansion based on xp->xp_context and "rmp".
-static int ExpandOther(expand_T *xp, regmatch_T *rmp, char ***matches, int *numMatches)
+static int ExpandOther(char *pat, expand_T *xp, regmatch_T *rmp, char ***matches, int *numMatches)
{
typedef CompleteListItemGetter ExpandFunc;
static struct expgen {
@@ -2399,6 +2618,8 @@ static int ExpandOther(expand_T *xp, regmatch_T *rmp, char ***matches, int *numM
{ EXPAND_ENV_VARS, get_env_name, true, true },
{ EXPAND_USER, get_users, true, false },
{ EXPAND_ARGLIST, get_arglist_name, true, false },
+ { EXPAND_BREAKPOINT, get_breakadd_arg, true, true },
+ { EXPAND_SCRIPTNAMES, get_scriptnames_arg, true, false },
{ EXPAND_CHECKHEALTH, get_healthcheck_names, true, false },
};
int ret = FAIL;
@@ -2410,7 +2631,7 @@ static int ExpandOther(expand_T *xp, regmatch_T *rmp, char ***matches, int *numM
if (tab[i].ic) {
rmp->rm_ic = true;
}
- ExpandGeneric(xp, rmp, matches, numMatches, tab[i].func, tab[i].escaped);
+ ExpandGeneric(pat, xp, rmp, matches, numMatches, tab[i].func, tab[i].escaped);
ret = OK;
break;
}
@@ -2450,9 +2671,11 @@ static int map_wildopts_to_ewflags(int options)
/// @param options WILD_ flags
static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numMatches, int options)
{
- regmatch_T regmatch;
+ regmatch_T regmatch = { .rm_ic = false };
int ret;
int flags = map_wildopts_to_ewflags(options);
+ const bool fuzzy = cmdline_fuzzy_complete(pat)
+ && cmdline_fuzzy_completion_supported(xp);
if (xp->xp_context == EXPAND_FILES
|| xp->xp_context == EXPAND_DIRECTORIES
@@ -2493,11 +2716,11 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM
}
if (xp->xp_context == EXPAND_COLORS) {
char *directories[] = { "colors", NULL };
- return ExpandRTDir(pat, DIP_START + DIP_OPT + DIP_LUA, numMatches, matches, directories);
+ return ExpandRTDir(pat, DIP_START + DIP_OPT, numMatches, matches, directories);
}
if (xp->xp_context == EXPAND_COMPILER) {
char *directories[] = { "compiler", NULL };
- return ExpandRTDir(pat, DIP_LUA, numMatches, matches, directories);
+ return ExpandRTDir(pat, 0, numMatches, matches, directories);
}
if (xp->xp_context == EXPAND_OWNSYNTAX) {
char *directories[] = { "syntax", NULL };
@@ -2505,7 +2728,7 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM
}
if (xp->xp_context == EXPAND_FILETYPE) {
char *directories[] = { "syntax", "indent", "ftplugin", NULL };
- return ExpandRTDir(pat, DIP_LUA, numMatches, matches, directories);
+ return ExpandRTDir(pat, 0, numMatches, matches, directories);
}
if (xp->xp_context == EXPAND_USER_LIST) {
return ExpandUserList(xp, matches, numMatches);
@@ -2516,6 +2739,9 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM
if (xp->xp_context == EXPAND_PACKADD) {
return ExpandPackAddDir(pat, numMatches, matches);
}
+ if (xp->xp_context == EXPAND_RUNTIME) {
+ return expand_runtime_cmd(pat, numMatches, matches);
+ }
// When expanding a function name starting with s:, match the <SNR>nr_
// prefix.
@@ -2533,26 +2759,30 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM
return nlua_expand_pat(xp, pat, numMatches, matches);
}
- regmatch.regprog = vim_regcomp(pat, magic_isset() ? RE_MAGIC : 0);
- if (regmatch.regprog == NULL) {
- return FAIL;
- }
+ if (!fuzzy) {
+ regmatch.regprog = vim_regcomp(pat, magic_isset() ? RE_MAGIC : 0);
+ if (regmatch.regprog == NULL) {
+ return FAIL;
+ }
- // set ignore-case according to p_ic, p_scs and pat
- regmatch.rm_ic = ignorecase(pat);
+ // set ignore-case according to p_ic, p_scs and pat
+ regmatch.rm_ic = ignorecase(pat);
+ }
if (xp->xp_context == EXPAND_SETTINGS
|| xp->xp_context == EXPAND_BOOL_SETTINGS) {
- ret = ExpandSettings(xp, &regmatch, numMatches, matches);
+ ret = ExpandSettings(xp, &regmatch, pat, numMatches, matches, fuzzy);
} else if (xp->xp_context == EXPAND_MAPPINGS) {
- ret = ExpandMappings(&regmatch, numMatches, matches);
+ ret = ExpandMappings(pat, &regmatch, numMatches, matches);
} else if (xp->xp_context == EXPAND_USER_DEFINED) {
- ret = ExpandUserDefined(xp, &regmatch, matches, numMatches);
+ ret = ExpandUserDefined(pat, xp, &regmatch, matches, numMatches);
} else {
- ret = ExpandOther(xp, &regmatch, matches, numMatches);
+ ret = ExpandOther(pat, xp, &regmatch, matches, numMatches);
}
- vim_regfree(regmatch.regprog);
+ if (!fuzzy) {
+ vim_regfree(regmatch.regprog);
+ }
xfree(tofree);
return ret;
@@ -2565,72 +2795,107 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM
/// program. Matching strings are copied into an array, which is returned.
///
/// @param func returns a string from the list
-static void ExpandGeneric(expand_T *xp, regmatch_T *regmatch, char ***matches, int *numMatches,
- CompleteListItemGetter func, int escaped)
+static void ExpandGeneric(const char *const pat, expand_T *xp, regmatch_T *regmatch,
+ char ***matches, int *numMatches, CompleteListItemGetter func,
+ int escaped)
{
- int i;
- size_t count = 0;
- char *str;
+ const bool fuzzy = cmdline_fuzzy_complete(pat);
+ *matches = NULL;
+ *numMatches = 0;
- // count the number of matching names
- for (i = 0;; i++) {
- str = (*func)(xp, i);
- if (str == NULL) { // end of list
- break;
- }
- if (*str == NUL) { // skip empty strings
- continue;
- }
- if (vim_regexec(regmatch, str, (colnr_T)0)) {
- count++;
- }
- }
- if (count == 0) {
- return;
+ garray_T ga;
+ if (!fuzzy) {
+ ga_init(&ga, sizeof(char *), 30);
+ } else {
+ ga_init(&ga, sizeof(fuzmatch_str_T), 30);
}
- assert(count < INT_MAX);
- *numMatches = (int)count;
- *matches = xmalloc(count * sizeof(char *));
- // copy the matching names into allocated memory
- count = 0;
- for (i = 0;; i++) {
- str = (*func)(xp, i);
+ for (int i = 0;; i++) {
+ char *str = (*func)(xp, i);
if (str == NULL) { // End of list.
break;
}
if (*str == NUL) { // Skip empty strings.
continue;
}
- if (vim_regexec(regmatch, str, (colnr_T)0)) {
- if (escaped) {
- str = vim_strsave_escaped(str, " \t\\.");
+
+ bool match;
+ int score = 0;
+ if (xp->xp_pattern[0] != NUL) {
+ if (!fuzzy) {
+ match = vim_regexec(regmatch, str, (colnr_T)0);
} else {
- str = xstrdup(str);
+ score = fuzzy_match_str(str, pat);
+ match = (score != 0);
}
- (*matches)[count++] = str;
- if (func == get_menu_names) {
- // Test for separator added by get_menu_names().
- str += strlen(str) - 1;
- if (*str == '\001') {
- *str = '.';
- }
+ } else {
+ match = true;
+ }
+
+ if (!match) {
+ continue;
+ }
+
+ if (escaped) {
+ str = vim_strsave_escaped(str, " \t\\.");
+ } else {
+ str = xstrdup(str);
+ }
+
+ if (fuzzy) {
+ GA_APPEND(fuzmatch_str_T, &ga, ((fuzmatch_str_T){
+ .idx = ga.ga_len,
+ .str = str,
+ .score = score,
+ }));
+ } else {
+ GA_APPEND(char *, &ga, str);
+ }
+
+ if (func == get_menu_names) {
+ // Test for separator added by get_menu_names().
+ str += strlen(str) - 1;
+ if (*str == '\001') {
+ *str = '.';
}
}
}
- // Sort the results. Keep menu's in the specified order.
- if (xp->xp_context != EXPAND_MENUNAMES && xp->xp_context != EXPAND_MENUS) {
- if (xp->xp_context == EXPAND_EXPRESSION
- || xp->xp_context == EXPAND_FUNCTIONS
- || xp->xp_context == EXPAND_USER_FUNC) {
+ if (ga.ga_len == 0) {
+ return;
+ }
+
+ // Sort the matches when using regular expression matching and sorting
+ // applies to the completion context. Menus and scriptnames should be kept
+ // in the specified order.
+ const bool sort_matches = !fuzzy
+ && xp->xp_context != EXPAND_MENUNAMES
+ && xp->xp_context != EXPAND_MENUS
+ && xp->xp_context != EXPAND_SCRIPTNAMES;
+
+ // <SNR> functions should be sorted to the end.
+ const bool funcsort = xp->xp_context == EXPAND_EXPRESSION
+ || xp->xp_context == EXPAND_FUNCTIONS
+ || xp->xp_context == EXPAND_USER_FUNC;
+
+ // Sort the matches.
+ if (sort_matches) {
+ if (funcsort) {
// <SNR> functions should be sorted to the end.
- qsort((void *)(*matches), (size_t)(*numMatches), sizeof(char *), sort_func_compare);
+ qsort(ga.ga_data, (size_t)ga.ga_len, sizeof(char *), sort_func_compare);
} else {
- sort_strings(*matches, *numMatches);
+ sort_strings(ga.ga_data, ga.ga_len);
}
}
+ if (!fuzzy) {
+ *matches = ga.ga_data;
+ *numMatches = ga.ga_len;
+ } else {
+ fuzzymatches_to_strmatches(ga.ga_data, matches, ga.ga_len, funcsort);
+ *numMatches = ga.ga_len;
+ }
+
// Reset the variables used for special highlight names expansion, so that
// they don't show up when getting normal highlight names by ID.
reset_expand_highlight();
@@ -2647,30 +2912,31 @@ static void expand_shellcmd_onedir(char *buf, char *s, size_t l, char *pat, char
// Expand matches in one directory of $PATH.
int ret = expand_wildcards(1, &buf, numMatches, matches, flags);
- if (ret == OK) {
- ga_grow(gap, *numMatches);
- {
- for (int i = 0; i < *numMatches; i++) {
- char *name = (*matches)[i];
-
- if (strlen(name) > l) {
- // Check if this name was already found.
- hash_T hash = hash_hash((char_u *)name + l);
- hashitem_T *hi =
- hash_lookup(ht, (const char *)(name + l), strlen(name + l), hash);
- if (HASHITEM_EMPTY(hi)) {
- // Remove the path that was prepended.
- STRMOVE(name, name + l);
- ((char **)gap->ga_data)[gap->ga_len++] = name;
- hash_add_item(ht, hi, (char_u *)name, hash);
- name = NULL;
- }
- }
- xfree(name);
+ if (ret != OK) {
+ return;
+ }
+
+ ga_grow(gap, *numMatches);
+
+ for (int i = 0; i < *numMatches; i++) {
+ char *name = (*matches)[i];
+
+ if (strlen(name) > l) {
+ // Check if this name was already found.
+ hash_T hash = hash_hash(name + l);
+ hashitem_T *hi =
+ hash_lookup(ht, (const char *)(name + l), strlen(name + l), hash);
+ if (HASHITEM_EMPTY(hi)) {
+ // Remove the path that was prepended.
+ STRMOVE(name, name + l);
+ ((char **)gap->ga_data)[gap->ga_len++] = name;
+ hash_add_item(ht, hi, name, hash);
+ name = NULL;
}
- xfree(*matches);
}
+ xfree(name);
}
+ xfree(*matches);
}
/// Complete a shell command.
@@ -2710,7 +2976,7 @@ static void expand_shellcmd(char *filepat, char ***matches, int *numMatches, int
path = ".";
} else {
// For an absolute name we don't use $PATH.
- if (!path_is_absolute((char_u *)pat)) {
+ if (!path_is_absolute(pat)) {
path = vim_getenv("PATH");
}
if (path == NULL) {
@@ -2809,22 +3075,28 @@ static void *call_user_expand_func(user_expand_func_T user_expand_func, expand_T
return ret;
}
-/// Expand names with a function defined by the user.
-static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, char ***matches, int *numMatches)
+/// Expand names with a function defined by the user (EXPAND_USER_DEFINED and
+/// EXPAND_USER_LIST).
+static int ExpandUserDefined(const char *const pat, expand_T *xp, regmatch_T *regmatch,
+ char ***matches, int *numMatches)
{
- char *e;
- garray_T ga;
-
+ const bool fuzzy = cmdline_fuzzy_complete(pat);
*matches = NULL;
*numMatches = 0;
- char *const retstr = call_user_expand_func((user_expand_func_T)call_func_retstr, xp);
+ char *const retstr = call_user_expand_func((user_expand_func_T)call_func_retstr, xp);
if (retstr == NULL) {
return FAIL;
}
- ga_init(&ga, (int)sizeof(char *), 3);
- for (char *s = retstr; *s != NUL; s = e) {
+ garray_T ga;
+ if (!fuzzy) {
+ ga_init(&ga, (int)sizeof(char *), 3);
+ } else {
+ ga_init(&ga, (int)sizeof(fuzmatch_str_T), 3);
+ }
+
+ for (char *s = retstr, *e; *s != NUL; s = e) {
e = vim_strchr(s, '\n');
if (e == NULL) {
e = s + strlen(s);
@@ -2832,10 +3104,31 @@ static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, char ***matches
const char keep = *e;
*e = NUL;
- const bool skip = xp->xp_pattern[0] && vim_regexec(regmatch, s, (colnr_T)0) == 0;
+ bool match;
+ int score = 0;
+ if (xp->xp_pattern[0] != NUL) {
+ if (!fuzzy) {
+ match = vim_regexec(regmatch, s, (colnr_T)0);
+ } else {
+ score = fuzzy_match_str(s, pat);
+ match = (score != 0);
+ }
+ } else {
+ match = true; // match everything
+ }
+
*e = keep;
- if (!skip) {
- GA_APPEND(char *, &ga, xstrnsave(s, (size_t)(e - s)));
+
+ if (match) {
+ if (!fuzzy) {
+ GA_APPEND(char *, &ga, xstrnsave(s, (size_t)(e - s)));
+ } else {
+ GA_APPEND(fuzmatch_str_T, &ga, ((fuzmatch_str_T){
+ .idx = ga.ga_len,
+ .str = xstrnsave(s, (size_t)(e - s)),
+ .score = score,
+ }));
+ }
}
if (*e != NUL) {
@@ -2843,8 +3136,18 @@ static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, char ***matches
}
}
xfree(retstr);
- *matches = ga.ga_data;
- *numMatches = ga.ga_len;
+
+ if (ga.ga_len == 0) {
+ return OK;
+ }
+
+ if (!fuzzy) {
+ *matches = ga.ga_data;
+ *numMatches = ga.ga_len;
+ } else {
+ fuzzymatches_to_strmatches(ga.ga_data, matches, ga.ga_len, false);
+ *numMatches = ga.ga_len;
+ }
return OK;
}
@@ -2907,11 +3210,12 @@ static int ExpandUserLua(expand_T *xp, int *num_file, char ***file)
/// Expand `file` for all comma-separated directories in `path`.
/// Adds matches to `ga`.
-void globpath(char *path, char *file, garray_T *ga, int expand_options)
+/// If "dirs" is true only expand directory names.
+void globpath(char *path, char *file, garray_T *ga, int expand_options, bool dirs)
{
expand_T xpc;
ExpandInit(&xpc);
- xpc.xp_context = EXPAND_FILES;
+ xpc.xp_context = dirs ? EXPAND_DIRECTORIES : EXPAND_FILES;
char *buf = xmalloc(MAXPATHL);
@@ -3077,8 +3381,7 @@ static int wildmenu_process_key_filenames(CmdlineInfo *cclp, int key, expand_T *
j -= utf_head_off(cclp->cmdbuff, cclp->cmdbuff + j);
if (vim_ispathsep(cclp->cmdbuff[j])
#ifdef BACKSLASH_IN_FILENAME
- && vim_strchr((const char_u *)" *?[{`$%#", cclp->cmdbuff[j + 1])
- == NULL
+ && vim_strchr(" *?[{`$%#", (uint8_t)cclp->cmdbuff[j + 1]) == NULL
#endif
) {
if (found) {
@@ -3231,14 +3534,23 @@ void f_getcompletion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
set_context_in_menu_cmd(&xpc, "menu", xpc.xp_pattern, false);
xpc.xp_pattern_len = strlen(xpc.xp_pattern);
}
-
if (xpc.xp_context == EXPAND_SIGN) {
set_context_in_sign_cmd(&xpc, xpc.xp_pattern);
xpc.xp_pattern_len = strlen(xpc.xp_pattern);
}
+ if (xpc.xp_context == EXPAND_RUNTIME) {
+ set_context_in_runtime_cmd(&xpc, xpc.xp_pattern);
+ xpc.xp_pattern_len = strlen(xpc.xp_pattern);
+ }
theend:
- pat = addstar(xpc.xp_pattern, xpc.xp_pattern_len, xpc.xp_context);
+ if (cmdline_fuzzy_completion_supported(&xpc)) {
+ // when fuzzy matching, don't modify the search string
+ pat = xstrdup(xpc.xp_pattern);
+ } else {
+ pat = addstar(xpc.xp_pattern, xpc.xp_pattern_len, xpc.xp_context);
+ }
+
ExpandOne(&xpc, pat, NULL, options, WILD_ALL_KEEP);
tv_list_alloc_ret(rettv, xpc.xp_numfiles);
diff --git a/src/nvim/cmdexpand.h b/src/nvim/cmdexpand.h
index cdd6192086..810e289f7c 100644
--- a/src/nvim/cmdexpand.h
+++ b/src/nvim/cmdexpand.h
@@ -19,8 +19,8 @@ enum {
WILD_ALL_KEEP = 8,
WILD_CANCEL = 9,
WILD_APPLY = 10,
- // WILD_PAGEUP = 11, not ported yet
- // WILD_PAGEDOWN = 12, not ported yet
+ WILD_PAGEUP = 11,
+ WILD_PAGEDOWN = 12,
WILD_PUM_WANT = 13,
};
diff --git a/src/nvim/cmdhist.c b/src/nvim/cmdhist.c
index d12ac87bbb..2df82d9355 100644
--- a/src/nvim/cmdhist.c
+++ b/src/nvim/cmdhist.c
@@ -280,7 +280,7 @@ static HistoryType get_histtype(const char *const name, const size_t len, const
}
}
- if (vim_strchr(":=@>?/", name[0]) != NULL && len == 1) {
+ if (vim_strchr(":=@>?/", (uint8_t)name[0]) != NULL && len == 1) {
return hist_char2type(name[0]);
}
@@ -437,7 +437,7 @@ int clr_history(const int histype)
/// Remove all entries matching {str} from a history.
///
/// @param histype may be one of the HIST_ values.
-static int del_history_entry(int histype, char_u *str)
+static int del_history_entry(int histype, char *str)
{
if (hislen == 0 || histype < 0 || histype >= HIST_COUNT || *str == NUL
|| hisidx[histype] < 0) {
@@ -446,7 +446,7 @@ static int del_history_entry(int histype, char_u *str)
const int idx = hisidx[histype];
regmatch_T regmatch;
- regmatch.regprog = vim_regcomp((char *)str, RE_MAGIC + RE_STRING);
+ regmatch.regprog = vim_regcomp(str, RE_MAGIC + RE_STRING);
if (regmatch.regprog == NULL) {
return false;
}
@@ -560,7 +560,7 @@ void f_histdel(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
// string given: remove all matching entries
char buf[NUMBUFLEN];
n = del_history_entry(get_histtype(str, strlen(str), false),
- (char_u *)tv_get_string_buf(&argvars[1], buf));
+ (char *)tv_get_string_buf(&argvars[1], buf));
}
rettv->vval.v_number = n;
}
@@ -611,7 +611,7 @@ void ex_history(exarg_T *eap)
int idx;
int i, j, k;
char *end;
- char_u *arg = (char_u *)eap->arg;
+ char *arg = eap->arg;
if (hislen == 0) {
msg(_("'history' option is zero"));
@@ -619,12 +619,12 @@ void ex_history(exarg_T *eap)
}
if (!(ascii_isdigit(*arg) || *arg == '-' || *arg == ',')) {
- end = (char *)arg;
+ end = arg;
while (ASCII_ISALPHA(*end)
- || vim_strchr(":=@>/?", *end) != NULL) {
+ || vim_strchr(":=@>/?", (uint8_t)(*end)) != NULL) {
end++;
}
- histype1 = get_histtype((const char *)arg, (size_t)(end - (char *)arg), false);
+ histype1 = get_histtype(arg, (size_t)(end - arg), false);
if (histype1 == HIST_INVALID) {
if (STRNICMP(arg, "all", end - (char *)arg) == 0) {
histype1 = 0;
@@ -637,7 +637,7 @@ void ex_history(exarg_T *eap)
histype2 = histype1;
}
} else {
- end = (char *)arg;
+ end = arg;
}
if (!get_list_range(&end, &hisidx1, &hisidx2) || *end != NUL) {
semsg(_(e_trailing_arg), end);
diff --git a/src/nvim/context.c b/src/nvim/context.c
index b064a92b74..9de6c16536 100644
--- a/src/nvim/context.c
+++ b/src/nvim/context.c
@@ -5,7 +5,9 @@
#include <assert.h>
#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
+#include <string.h>
#include "nvim/api/private/converter.h"
#include "nvim/api/private/helpers.h"
@@ -23,8 +25,6 @@
#include "nvim/message.h"
#include "nvim/option.h"
#include "nvim/shada.h"
-#include "nvim/types.h"
-#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "context.c.generated.h"
diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c
index 3dfbcd1f81..f7e70a78ce 100644
--- a/src/nvim/debugger.c
+++ b/src/nvim/debugger.c
@@ -403,7 +403,7 @@ void ex_debug(exarg_T *eap)
debug_break_level = debug_break_level_save;
}
-static char_u *debug_breakpoint_name = NULL;
+static char *debug_breakpoint_name = NULL;
static linenr_T debug_breakpoint_lnum;
/// When debugging or a breakpoint is set on a skipped command, no debug prompt
@@ -412,7 +412,7 @@ static linenr_T debug_breakpoint_lnum;
/// a skipped command decides itself that a debug prompt should be displayed, it
/// can do so by calling dbg_check_skipped().
static int debug_skipped;
-static char_u *debug_skipped_name;
+static char *debug_skipped_name;
/// Go to debug mode when a breakpoint was encountered or "ex_nesting_level" is
/// at or below the break level. But only when the line is actually
@@ -426,8 +426,8 @@ void dbg_check_breakpoint(exarg_T *eap)
if (!eap->skip) {
char *p;
// replace K_SNR with "<SNR>"
- if (debug_breakpoint_name[0] == K_SPECIAL
- && debug_breakpoint_name[1] == KS_EXTRA
+ if ((uint8_t)debug_breakpoint_name[0] == K_SPECIAL
+ && (uint8_t)debug_breakpoint_name[1] == KS_EXTRA
&& debug_breakpoint_name[2] == KE_SNR) {
p = "<SNR>";
} else {
@@ -802,7 +802,7 @@ static linenr_T debuggy_find(bool file, char *fname, linenr_T after, garray_T *g
// while matching should abort it.
prev_got_int = got_int;
got_int = false;
- if (vim_regexec_prog(&bp->dbg_prog, false, (char_u *)name, (colnr_T)0)) {
+ if (vim_regexec_prog(&bp->dbg_prog, false, name, (colnr_T)0)) {
lnum = bp->dbg_lnum;
if (fp != NULL) {
*fp = bp->dbg_forceit;
@@ -857,6 +857,6 @@ static linenr_T debuggy_find(bool file, char *fname, linenr_T after, garray_T *g
void dbg_breakpoint(char *name, linenr_T lnum)
{
// We need to check if this line is actually executed in do_one_cmd()
- debug_breakpoint_name = (char_u *)name;
+ debug_breakpoint_name = name;
debug_breakpoint_lnum = lnum;
}
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index 037eb9f0d9..63c55ec602 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -7,6 +7,7 @@
#include "nvim/decoration.h"
#include "nvim/drawscreen.h"
#include "nvim/extmark.h"
+#include "nvim/fold.h"
#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
#include "nvim/memory.h"
@@ -407,7 +408,7 @@ void decor_redraw_signs(buf_T *buf, int row, int *num_signs, SignTextAttrs sattr
}
if (j < SIGN_SHOW_MAX) {
sattrs[j] = (SignTextAttrs) {
- .text = (char *)decor->sign_text,
+ .text = decor->sign_text,
.hl_attr_id = decor->sign_hl_id == 0 ? 0 : syn_id2attr(decor->sign_hl_id),
.priority = decor->priority
};
@@ -550,7 +551,8 @@ void decor_add_ephemeral(int start_row, int start_col, int end_row, int end_col,
decor_add(&decor_state, start_row, start_col, end_row, end_col, decor, true, ns_id, mark_id);
}
-int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines)
+/// @param has_fold whether line "lnum" has a fold, or kNone when not calculated yet
+int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines, TriState has_fold)
{
buf_T *buf = wp->w_buffer;
if (!buf->b_virt_line_blocks) {
@@ -564,6 +566,10 @@ int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines)
int end_row = (int)lnum;
MarkTreeIter itr[1] = { 0 };
marktree_itr_get(buf->b_marktree, row, 0, itr);
+ bool below_fold = lnum > 1 && hasFoldingWin(wp, lnum - 1, NULL, NULL, true, NULL);
+ if (has_fold == kNone) {
+ has_fold = hasFoldingWin(wp, lnum, NULL, NULL, true, NULL);
+ }
while (true) {
mtkey_t mark = marktree_itr_current(itr);
if (mark.pos.row < 0 || mark.pos.row >= end_row) {
@@ -572,8 +578,9 @@ int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines)
goto next_mark;
}
bool above = mark.pos.row > (lnum - 2);
+ bool has_fold_cur = above ? has_fold : below_fold;
Decoration *decor = mark.decor_full;
- if (decor && decor->virt_lines_above == above) {
+ if (!has_fold_cur && decor && decor->virt_lines_above == above) {
virt_lines += (int)kv_size(decor->virt_lines);
if (lines) {
kv_splice(*lines, decor->virt_lines);
diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h
index cee1eb2f94..c9ec8ede7f 100644
--- a/src/nvim/decoration.h
+++ b/src/nvim/decoration.h
@@ -58,7 +58,7 @@ struct Decoration {
DecorPriority priority;
int col; // fixed col value, like win_col
int virt_text_width; // width of virt_text
- char_u *sign_text;
+ char *sign_text;
int sign_hl_id;
int number_hl_id;
int line_hl_id;
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 45f00cb41e..032de561b3 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -1218,7 +1218,7 @@ void ex_diffpatch(exarg_T *eap)
fullname = FullName_save(eap->arg, false);
esc_name = vim_strsave_shellescape(fullname != NULL ? fullname : eap->arg, true, true);
#else
- esc_name = (char *)vim_strsave_shellescape(eap->arg, true, true);
+ esc_name = vim_strsave_shellescape(eap->arg, true, true);
#endif
size_t buflen = strlen(tmp_orig) + strlen(esc_name) + strlen(tmp_new) + 16;
buf = xmalloc(buflen);
@@ -1575,7 +1575,7 @@ static bool extract_hunk(FILE *fd, diffhunk_T *hunk, diffstyle_T *diffstyle)
// --- file1 2018-03-20 13:23:35.783153140 +0100
// +++ file2 2018-03-20 13:23:41.183156066 +0100
// @@ -1,3 +1,5 @@
- if (isdigit(*line)) {
+ if (isdigit((uint8_t)(*line))) {
*diffstyle = DIFF_ED;
} else if ((strncmp(line, "@@ ", 3) == 0)) {
*diffstyle = DIFF_UNIFIED;
@@ -1593,7 +1593,7 @@ static bool extract_hunk(FILE *fd, diffhunk_T *hunk, diffstyle_T *diffstyle)
}
if (*diffstyle == DIFF_ED) {
- if (!isdigit(*line)) {
+ if (!isdigit((uint8_t)(*line))) {
continue; // not the start of a diff block
}
if (parse_diff_ed(line, hunk) == FAIL) {
@@ -2293,7 +2293,7 @@ static bool diff_equal_char(const char *const p1, const char *const p2, int *con
static int diff_cmp(char *s1, char *s2)
{
if ((diff_flags & DIFF_IBLANK)
- && (*(char_u *)skipwhite(s1) == NUL || *skipwhite(s2) == NUL)) {
+ && (*skipwhite(s1) == NUL || *skipwhite(s2) == NUL)) {
return 0;
}
diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c
index 33038dfb9f..a057978a5e 100644
--- a/src/nvim/digraph.c
+++ b/src/nvim/digraph.c
@@ -1489,7 +1489,7 @@ int do_digraph(int c)
/// Find a digraph for "val". If found return the string to display it.
/// If not found return NULL.
-char_u *get_digraph_for_char(int val_arg)
+char *get_digraph_for_char(int val_arg)
{
const int val = val_arg;
const digr_T *dp;
@@ -1506,7 +1506,7 @@ char_u *get_digraph_for_char(int val_arg)
r[0] = dp->char1;
r[1] = dp->char2;
r[2] = NUL;
- return r;
+ return (char *)r;
}
dp++;
}
@@ -1749,16 +1749,16 @@ static void digraph_getlist_appendpair(const digr_T *dp, list_T *l)
list_T *l2 = tv_list_alloc(2);
tv_list_append_list(l, l2);
- char_u buf[30];
- buf[0] = dp->char1;
- buf[1] = dp->char2;
+ char buf[30];
+ buf[0] = (char)dp->char1;
+ buf[1] = (char)dp->char2;
buf[2] = NUL;
- tv_list_append_string(l2, (char *)buf, -1);
+ tv_list_append_string(l2, buf, -1);
- char_u *p = buf;
- p += utf_char2bytes(dp->result, (char *)p);
+ char *p = buf;
+ p += utf_char2bytes(dp->result, p);
*p = NUL;
- tv_list_append_string(l2, (char *)buf, -1);
+ tv_list_append_string(l2, buf, -1);
}
void digraph_getlist_common(bool list_all, typval_T *rettv)
@@ -1824,7 +1824,7 @@ struct dg_header_entry {
static void printdigraph(const digr_T *dp, result_T *previous)
FUNC_ATTR_NONNULL_ARG(1)
{
- char_u buf[30];
+ char buf[30];
int list_width = 13;
if (dp->result == 0) {
@@ -1854,29 +1854,29 @@ static void printdigraph(const digr_T *dp, result_T *previous)
}
}
- char_u *p = &buf[0];
- *p++ = dp->char1;
- *p++ = dp->char2;
+ char *p = &buf[0];
+ *p++ = (char)dp->char1;
+ *p++ = (char)dp->char2;
*p++ = ' ';
*p = NUL;
- msg_outtrans((char *)buf);
+ msg_outtrans(buf);
p = buf;
// add a space to draw a composing char on
if (utf_iscomposing(dp->result)) {
*p++ = ' ';
}
- p += utf_char2bytes(dp->result, (char *)p);
+ p += utf_char2bytes(dp->result, p);
*p = NUL;
- msg_outtrans_attr((char *)buf, HL_ATTR(HLF_8));
+ msg_outtrans_attr(buf, HL_ATTR(HLF_8));
p = buf;
if (char2cells(dp->result) == 1) {
*p++ = ' ';
}
assert(p >= buf);
- vim_snprintf((char *)p, sizeof(buf) - (size_t)(p - buf), " %3d", dp->result);
- msg_outtrans((char *)buf);
+ vim_snprintf(p, sizeof(buf) - (size_t)(p - buf), " %3d", dp->result);
+ msg_outtrans(buf);
}
/// Get the two digraph characters from a typval.
@@ -1885,7 +1885,7 @@ static int get_digraph_chars(const typval_T *arg, int *char1, int *char2)
{
char buf_chars[NUMBUFLEN];
const char *chars = tv_get_string_buf_chk(arg, buf_chars);
- const char_u *p = (const char_u *)chars;
+ const char *p = chars;
if (p != NULL) {
if (*p != NUL) {
@@ -1917,7 +1917,7 @@ static bool digraph_set_common(const typval_T *argchars, const typval_T *argdigr
if (digraph == NULL) {
return false;
}
- const char_u *p = (const char_u *)digraph;
+ const char *p = digraph;
int n = mb_cptr2char_adv(&p);
if (*p != NUL) {
semsg(_(e_digraph_argument_must_be_one_character_str), digraph);
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index 8fc1a4b029..01ff207c2b 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -400,40 +400,56 @@ static int get_sign_attrs(buf_T *buf, linenr_T lnum, SignTextAttrs *sattrs, int
/// Prepare and build the 'statuscolumn' string for line "lnum" in window "wp".
/// Fill "stcp" with the built status column string and attributes.
+/// This can be called three times per win_line(), once for virt_lines, once for
+/// the start of the buffer line "lnum" and once for the wrapped lines.
///
/// @param[out] stcp Status column attributes
static void get_statuscol_str(win_T *wp, linenr_T lnum, int row, int startrow, int filler_lines,
- int cul_attr, int sign_num_attr, int sign_cul_attr, char_u *extra,
- foldinfo_T foldinfo, SignTextAttrs *sattrs, statuscol_T *stcp)
+ int cul_attr, int sign_num_attr, int sign_cul_attr, statuscol_T *stcp,
+ foldinfo_T foldinfo, SignTextAttrs *sattrs)
{
- long relnum = 0;
- bool wrapped = row != startrow + filler_lines;
+ long relnum = -1;
bool use_cul = use_cursor_line_sign(wp, lnum);
+ int virtnum = row - startrow - filler_lines;
- // Set num, fold and sign text and attrs, empty when wrapped
- if (row == startrow) {
- relnum = labs(get_cursor_rel_lnum(wp, lnum));
+ // When called the first time for line "lnum" set num_attr
+ if (stcp->num_attr == 0) {
stcp->num_attr = sign_num_attr ? sign_num_attr
: get_line_number_attr(wp, lnum, row, startrow, filler_lines);
-
+ }
+ // When called for the first non-filler row of line "lnum" set num v:vars and fold column
+ if (virtnum == 0) {
+ relnum = labs(get_cursor_rel_lnum(wp, lnum));
if (compute_foldcolumn(wp, 0)) {
size_t n = fill_foldcolumn(stcp->fold_text, wp, foldinfo, lnum);
stcp->fold_text[n] = NUL;
stcp->fold_attr = win_hl_attr(wp, use_cul ? HLF_CLF : HLF_FC);
}
}
-
+ // Make sure to clear->set->clear sign column for filler->first->wrapped lines
int i = 0;
for (; i < wp->w_scwidth; i++) {
- SignTextAttrs *sattr = wrapped ? NULL : sign_get_attr(i, sattrs, wp->w_scwidth);
+ SignTextAttrs *sattr = virtnum ? NULL : sign_get_attr(i, sattrs, wp->w_scwidth);
stcp->sign_text[i] = sattr && sattr->text ? sattr->text : " ";
stcp->sign_attr[i] = sattr ? (use_cul && sign_cul_attr ? sign_cul_attr : sattr->hl_attr_id)
: win_hl_attr(wp, use_cul ? HLF_CLS : HLF_SC);
}
stcp->sign_text[i] = NULL;
- int width = build_statuscol_str(wp, row == startrow, wrapped, lnum, relnum,
- stcp->width, ' ', stcp->text, &stcp->hlrec, stcp);
+ // When a buffer's line count has changed, make a best estimate for the full
+ // width of the status column by building with "w_nrwidth_line_count". Add
+ // potentially truncated width and rebuild before drawing anything.
+ if (wp->w_statuscol_line_count != wp->w_nrwidth_line_count) {
+ wp->w_statuscol_line_count = wp->w_nrwidth_line_count;
+ set_vim_var_nr(VV_VIRTNUM, 0);
+ build_statuscol_str(wp, wp->w_nrwidth_line_count, 0, stcp->width,
+ ' ', stcp->text, &stcp->hlrec, stcp);
+ stcp->width += stcp->truncate;
+ }
+ set_vim_var_nr(VV_VIRTNUM, virtnum);
+
+ int width = build_statuscol_str(wp, lnum, relnum, stcp->width,
+ ' ', stcp->text, &stcp->hlrec, stcp);
// Force a redraw in case of error or when truncated
if (*wp->w_p_stc == NUL || (stcp->truncate > 0 && wp->w_nrwidth < MAX_NUMBERWIDTH)) {
if (stcp->truncate) { // Avoid truncating 'statuscolumn'
@@ -466,9 +482,8 @@ static void get_statuscol_str(win_T *wp, linenr_T lnum, int row, int startrow, i
///
/// @param stcp Status column attributes
/// @param[out] draw_state Current draw state in win_line()
-static void get_statuscol_display_info(LineDrawState *draw_state, int *char_attr, int *n_extrap,
- int *c_extrap, int *c_finalp, char_u *extra, char **pp_extra,
- statuscol_T *stcp)
+static void get_statuscol_display_info(statuscol_T *stcp, LineDrawState *draw_state, int *char_attr,
+ int *n_extrap, int *c_extrap, int *c_finalp, char **pp_extra)
{
*c_extrap = NUL;
*c_finalp = NUL;
@@ -509,7 +524,7 @@ static bool use_cursor_line_nr(win_T *wp, linenr_T lnum, int row, int startrow,
&& (wp->w_p_culopt_flags & CULOPT_LINE)));
}
-static inline void get_line_number_str(win_T *wp, linenr_T lnum, char_u *buf, size_t buf_len)
+static inline void get_line_number_str(win_T *wp, linenr_T lnum, char *buf, size_t buf_len)
{
long num;
char *fmt = "%*ld ";
@@ -527,7 +542,7 @@ static inline void get_line_number_str(win_T *wp, linenr_T lnum, char_u *buf, si
}
}
- snprintf((char *)buf, buf_len, fmt, number_width(wp), num);
+ snprintf(buf, buf_len, fmt, number_width(wp), num);
}
static int get_line_number_attr(win_T *wp, linenr_T lnum, int row, int startrow, int filler_lines)
@@ -608,7 +623,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
int row; // row in the window, excl w_winrow
ScreenGrid *grid = &wp->w_grid; // grid specific to the window
- char_u extra[57]; // sign, line number and 'fdc' must
+ char extra[57]; // sign, line number and 'fdc' must
// fit in here
int n_extra = 0; // number of extra chars
char *p_extra = NULL; // string of extra chars, plus NUL
@@ -802,7 +817,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
nextline[SPWORDLEN] = NUL;
if (lnum < wp->w_buffer->b_ml.ml_line_count) {
line = ml_get_buf(wp->w_buffer, lnum + 1, false);
- spell_cat_line(nextline + SPWORDLEN, (char_u *)line, SPWORDLEN);
+ spell_cat_line(nextline + SPWORDLEN, line, SPWORDLEN);
}
// When a word wrapped from the previous line the start of the current
@@ -936,7 +951,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
area_highlighting = true;
}
VirtLines virt_lines = KV_INITIAL_VALUE;
- int n_virt_lines = decor_virt_lines(wp, lnum, &virt_lines);
+ int n_virt_lines = decor_virt_lines(wp, lnum, &virt_lines, has_fold);
filler_lines += n_virt_lines;
if (lnum == wp->w_topline) {
filler_lines = wp->w_topfill;
@@ -1128,7 +1143,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// no bad word found at line start, don't check until end of a
// word
spell_hlf = HLF_COUNT;
- word_end = (int)(spell_to_word_end((char_u *)ptr, wp) - (char_u *)line + 1);
+ word_end = (int)(spell_to_word_end(ptr, wp) - line + 1);
} else {
// bad word found, use attributes until end of word
assert(len <= INT_MAX);
@@ -1200,6 +1215,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
int sign_idx = 0;
+ int virt_line_index;
+ int virt_line_offset = -1;
// Repeat for the whole displayed line.
for (;;) {
int has_match_conc = 0; ///< match wants to conceal
@@ -1226,9 +1243,22 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
}
- // Skip fold, sign and number states if 'statuscolumn' is set.
- if (draw_state == WL_FOLD - 1 && n_extra == 0 && statuscol.draw) {
- draw_state = WL_STC - 1;
+ if (draw_state == WL_FOLD - 1 && n_extra == 0) {
+ if (filler_todo > 0) {
+ int index = filler_todo - (filler_lines - n_virt_lines);
+ if (index > 0) {
+ virt_line_index = (int)kv_size(virt_lines) - index;
+ assert(virt_line_index >= 0);
+ virt_line_offset = kv_A(virt_lines, virt_line_index).left_col ? 0 : win_col_off(wp);
+ }
+ }
+ if (!virt_line_offset) {
+ // Skip the column states if there is a "virt_left_col" line.
+ draw_state = WL_BRI - 1;
+ } else if (statuscol.draw) {
+ // Skip fold, sign and number states if 'statuscolumn' is set.
+ draw_state = WL_STC - 1;
+ }
}
if (draw_state == WL_FOLD - 1 && n_extra == 0) {
@@ -1259,7 +1289,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (wp->w_scwidth > 0) {
get_sign_display_info(false, wp, lnum, sattrs, row,
startrow, filler_lines, filler_todo,
- &c_extra, &c_final, (char *)extra, sizeof(extra),
+ &c_extra, &c_final, extra, sizeof(extra),
&p_extra, &n_extra, &char_attr, sign_idx,
sign_cul_attr);
sign_idx++;
@@ -1284,29 +1314,29 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u' && num_signs > 0) {
get_sign_display_info(true, wp, lnum, sattrs, row,
startrow, filler_lines, filler_todo,
- &c_extra, &c_final, (char *)extra, sizeof(extra),
+ &c_extra, &c_final, extra, sizeof(extra),
&p_extra, &n_extra, &char_attr, sign_idx,
sign_cul_attr);
} else {
// Draw the line number (empty space after wrapping).
if (row == startrow + filler_lines) {
- get_line_number_str(wp, lnum, (char_u *)extra, sizeof(extra));
+ get_line_number_str(wp, lnum, extra, sizeof(extra));
if (wp->w_skipcol > 0) {
- for (p_extra = (char *)extra; *p_extra == ' '; p_extra++) {
+ for (p_extra = extra; *p_extra == ' '; p_extra++) {
*p_extra = '-';
}
}
if (wp->w_p_rl) { // reverse line numbers
// like rl_mirror(), but keep the space at the end
- char *p2 = skipwhite((char *)extra);
+ char *p2 = skipwhite(extra);
p2 = skiptowhite(p2) - 1;
- for (char *p1 = skipwhite((char *)extra); p1 < p2; p1++, p2--) {
+ for (char *p1 = skipwhite(extra); p1 < p2; p1++, p2--) {
const char t = *p1;
*p1 = *p2;
*p2 = t;
}
}
- p_extra = (char *)extra;
+ p_extra = extra;
c_extra = NUL;
} else {
c_extra = ' ';
@@ -1327,14 +1357,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// Draw the 'statuscolumn' if option is set.
if (statuscol.draw) {
if (statuscol.textp == NULL) {
- get_statuscol_str(wp, lnum, row, startrow, filler_lines, cul_attr, sign_num_attr,
- sign_cul_attr, extra, foldinfo, sattrs, &statuscol);
+ get_statuscol_str(wp, lnum, row, startrow, filler_lines, cul_attr,
+ sign_num_attr, sign_cul_attr, &statuscol, foldinfo, sattrs);
if (wp->w_redr_statuscol) {
- return 0;
+ break;
}
}
- get_statuscol_display_info(&draw_state, &char_attr, &n_extra, &c_extra,
- &c_final, extra, &p_extra, &statuscol);
+ get_statuscol_display_info(&statuscol, &draw_state, &char_attr,
+ &n_extra, &c_extra, &c_final, &p_extra);
}
}
@@ -1413,7 +1443,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
char_attr = win_hl_attr(wp, HLF_DED);
}
- char *const sbr = (char *)get_showbreak_value(wp);
+ char *const sbr = get_showbreak_value(wp);
if (*sbr != NUL && need_showbreak) {
// Draw 'showbreak' at the start of each broken line.
p_extra = sbr;
@@ -1488,7 +1518,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
&& has_fold
&& col == win_col_offset
&& n_extra == 0
- && row == startrow) {
+ && row == startrow + filler_lines) {
char_attr = win_hl_attr(wp, HLF_FL);
linenr_T lnume = lnum + foldinfo.fi_lines - 1;
@@ -1509,7 +1539,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
&& has_fold
&& col < grid->cols
&& n_extra == 0
- && row == startrow) {
+ && row == startrow + filler_lines) {
// fill rest of line with 'fold'
c_extra = wp->w_p_fcs_chars.fold;
c_final = NUL;
@@ -1521,7 +1551,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
&& has_fold
&& col >= grid->cols
&& n_extra != 0
- && row == startrow) {
+ && row == startrow + filler_lines) {
// Truncate the folding.
n_extra = 0;
}
@@ -1710,14 +1740,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
|| (mb_l > 1 && (!vim_isprintc(mb_c)))) {
// Illegal UTF-8 byte: display as <xx>.
// Non-BMP character : display as ? or fullwidth ?.
- transchar_hex((char *)extra, mb_c);
+ transchar_hex(extra, mb_c);
if (wp->w_p_rl) { // reverse
- rl_mirror((char *)extra);
+ rl_mirror(extra);
}
- p_extra = (char *)extra;
+ p_extra = extra;
c = (uint8_t)(*p_extra);
- mb_c = mb_ptr2char_adv((const char_u **)&p_extra);
+ mb_c = mb_ptr2char_adv((const char **)&p_extra);
mb_utf8 = (c >= 0x80);
n_extra = (int)strlen(p_extra);
c_extra = NUL;
@@ -1805,7 +1835,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
syntax_attr = get_syntax_attr((colnr_T)v - 1,
has_spell ? &can_spell : NULL, false);
- if (did_emsg) {
+ if (did_emsg) { // -V547
wp->w_s->b_syn_error = true;
has_syntax = false;
} else {
@@ -1890,7 +1920,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
p = prev_ptr;
}
cap_col -= (int)(prev_ptr - line);
- size_t tmplen = spell_check(wp, (char_u *)p, &spell_hlf, &cap_col, nochange);
+ size_t tmplen = spell_check(wp, p, &spell_hlf, &cap_col, nochange);
assert(tmplen <= INT_MAX);
len = (int)tmplen;
word_end = (int)v + len;
@@ -1960,7 +1990,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// We have just drawn the showbreak value, no need to add
// space for it again.
if (vcol == vcol_sbr) {
- n_extra -= mb_charlen((char *)get_showbreak_value(wp));
+ n_extra -= mb_charlen(get_showbreak_value(wp));
if (n_extra < 0) {
n_extra = 0;
}
@@ -2056,12 +2086,12 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (c == TAB && (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) {
int tab_len = 0;
long vcol_adjusted = vcol; // removed showbreak length
- char_u *const sbr = get_showbreak_value(wp);
+ char *const sbr = get_showbreak_value(wp);
// Only adjust the tab_len, when at the first column after the
// showbreak value was drawn.
if (*sbr != NUL && vcol == vcol_sbr && wp->w_p_wrap) {
- vcol_adjusted = vcol - mb_charlen((char *)sbr);
+ vcol_adjusted = vcol - mb_charlen(sbr);
}
// tab amount depends on current column
tab_len = tabstop_padding((colnr_T)vcol_adjusted,
@@ -2734,7 +2764,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// At end of screen line and there is more to come: Display the line
// so far. If there is no more to display it is caught above.
if ((wp->w_p_rl ? (col < 0) : (col >= grid->cols))
- && foldinfo.fi_lines == 0
+ && (!has_fold || virt_line_offset >= 0)
&& (draw_state != WL_LINE
|| *ptr != NUL
|| filler_todo > 0
@@ -2751,15 +2781,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
&& !wp->w_p_rl; // Not right-to-left.
int draw_col = col - boguscols;
- if (filler_todo > 0) {
- int index = filler_todo - (filler_lines - n_virt_lines);
- if (index > 0) {
- int i = (int)kv_size(virt_lines) - index;
- assert(i >= 0);
- int offset = kv_A(virt_lines, i).left_col ? 0 : win_col_offset;
- draw_virt_text_item(buf, offset, kv_A(virt_lines, i).line,
- kHlModeReplace, grid->cols, 0);
- }
+ if (virt_line_offset >= 0) {
+ draw_virt_text_item(buf, virt_line_offset, kv_A(virt_lines, virt_line_index).line,
+ kHlModeReplace, grid->cols, 0);
} else {
draw_virt_text(wp, buf, win_col_offset, &draw_col, grid->cols, row);
}
@@ -2819,16 +2843,18 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
need_showbreak = true;
}
if (statuscol.draw) {
- if (row == startrow + 1 || row == startrow + filler_lines) {
+ if (row == startrow + filler_lines + 1 || row == startrow + filler_lines) {
// Re-evaluate 'statuscolumn' for the first wrapped row and non filler line
statuscol.textp = NULL;
- } else { // Otherwise just reset the text/hlrec pointers
+ } else if (statuscol.textp) {
+ // Draw the already built 'statuscolumn' on the next wrapped or filler line
statuscol.textp = statuscol.text;
statuscol.hlrecp = statuscol.hlrec;
} // Fall back to default columns if the 'n' flag isn't in 'cpo'
statuscol.draw = vim_strchr(p_cpo, CPO_NUMCOL) == NULL;
}
filler_todo--;
+ virt_line_offset = -1;
// When the filler lines are actually below the last line of the
// file, don't draw the line itself, break here.
if (filler_todo == 0 && (wp->w_botfill || end_fill)) {
diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c
index 568dbe99c0..04c342e068 100644
--- a/src/nvim/drawscreen.c
+++ b/src/nvim/drawscreen.c
@@ -126,12 +126,14 @@ static char *provider_err = NULL;
void conceal_check_cursor_line(void)
{
bool should_conceal = conceal_cursor_line(curwin);
- if (curwin->w_p_cole > 0 && (conceal_cursor_used != should_conceal)) {
- redrawWinline(curwin, curwin->w_cursor.lnum);
- // Need to recompute cursor column, e.g., when starting Visual mode
- // without concealing.
- curs_columns(curwin, true);
+ if (curwin->w_p_cole <= 0 || conceal_cursor_used == should_conceal) {
+ return;
}
+
+ redrawWinline(curwin, curwin->w_cursor.lnum);
+ // Need to recompute cursor column, e.g., when starting Visual mode
+ // without concealing.
+ curs_columns(curwin, true);
}
/// Resize default_grid to Rows and Columns.
@@ -837,25 +839,29 @@ static bool vsep_connected(win_T *wp, WindowCorner corner)
/// Draw the vertical separator right of window "wp"
static void draw_vsep_win(win_T *wp)
{
- if (wp->w_vsep_width) {
- // draw the vertical separator right of this window
- int hl;
- int c = fillchar_vsep(wp, &hl);
- grid_fill(&default_grid, wp->w_winrow, W_ENDROW(wp),
- W_ENDCOL(wp), W_ENDCOL(wp) + 1, c, ' ', hl);
+ if (!wp->w_vsep_width) {
+ return;
}
+
+ // draw the vertical separator right of this window
+ int hl;
+ int c = fillchar_vsep(wp, &hl);
+ grid_fill(&default_grid, wp->w_winrow, W_ENDROW(wp),
+ W_ENDCOL(wp), W_ENDCOL(wp) + 1, c, ' ', hl);
}
/// Draw the horizontal separator below window "wp"
static void draw_hsep_win(win_T *wp)
{
- if (wp->w_hsep_height) {
- // draw the horizontal separator below this window
- int hl;
- int c = fillchar_hsep(wp, &hl);
- grid_fill(&default_grid, W_ENDROW(wp), W_ENDROW(wp) + 1,
- wp->w_wincol, W_ENDCOL(wp), c, c, hl);
+ if (!wp->w_hsep_height) {
+ return;
}
+
+ // draw the horizontal separator below this window
+ int hl;
+ int c = fillchar_hsep(wp, &hl);
+ grid_fill(&default_grid, W_ENDROW(wp), W_ENDROW(wp) + 1,
+ wp->w_wincol, W_ENDCOL(wp), c, c, hl);
}
/// Get the separator connector for specified window corner of window "wp"
@@ -1906,7 +1912,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
if (j > 0 && !wp->w_botfill && row < wp->w_grid.rows) {
// Display filler text below last line. win_line() will check
// for ml_line_count+1 and only draw filler lines
- foldinfo_T info = FOLDINFO_INIT;
+ foldinfo_T info = { 0 };
row = win_line(wp, wp->w_botline, row, wp->w_grid.rows,
false, false, info, &line_providers, &provider_err);
}
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index b83e732cec..96df6a3044 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -107,10 +107,9 @@ static colnr_T Insstart_textlen; // length of line when insert started
static colnr_T Insstart_blank_vcol; // vcol for first inserted blank
static bool update_Insstart_orig = true; // set Insstart_orig to Insstart
-static char_u *last_insert = NULL; // the text of the previous insert,
- // K_SPECIAL is escaped
-static int last_insert_skip; // nr of chars in front of previous insert
-static int new_insert_skip; // nr of chars in front of current insert
+static char *last_insert = NULL; // the text of the previous insert, K_SPECIAL is escaped
+static int last_insert_skip; // nr of chars in front of previous insert
+static int new_insert_skip; // nr of chars in front of current insert
static int did_restart_edit; // "restart_edit" when calling edit()
static bool can_cindent; // may do cindenting on this line
@@ -324,7 +323,7 @@ static void insert_enter(InsertState *s)
// Get the current length of the redo buffer, those characters have to be
// skipped if we want to get to the inserted characters.
- s->ptr = (char *)get_inserted();
+ s->ptr = get_inserted();
if (s->ptr == NULL) {
new_insert_skip = 0;
} else {
@@ -558,12 +557,12 @@ static int insert_execute(VimState *state, int key)
// completion: Add to "compl_leader".
if (ins_compl_accept_char(s->c)) {
// Trigger InsertCharPre.
- char_u *str = do_insert_char_pre(s->c);
- char_u *p;
+ char *str = do_insert_char_pre(s->c);
+ char *p;
if (str != NULL) {
for (p = str; *p != NUL; MB_PTR_ADV(p)) {
- ins_compl_addleader(utf_ptr2char((char *)p));
+ ins_compl_addleader(utf_ptr2char(p));
}
xfree(str);
} else {
@@ -1122,7 +1121,7 @@ normalchar:
if (!p_paste) {
// Trigger InsertCharPre.
- char *str = (char *)do_insert_char_pre(s->c);
+ char *str = do_insert_char_pre(s->c);
char *p;
if (str != NULL) {
@@ -1544,8 +1543,8 @@ void display_dollar(colnr_T col)
curwin->w_cursor.col = col;
// If on the last byte of a multi-byte move to the first byte.
- char_u *p = (char_u *)get_cursor_line_ptr();
- curwin->w_cursor.col -= utf_head_off((char *)p, (char *)p + col);
+ char *p = get_cursor_line_ptr();
+ curwin->w_cursor.col -= utf_head_off(p, p + col);
curs_columns(curwin, false); // Recompute w_wrow and w_wcol
if (curwin->w_wcol < curwin->w_grid.cols) {
edit_putchar('$', false);
@@ -1579,7 +1578,7 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
int last_vcol;
int insstart_less; // reduction for Insstart.col
int new_cursor_col;
- char_u *ptr;
+ char *ptr;
int save_p_list;
int start_col;
colnr_T vc;
@@ -1658,9 +1657,9 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
// Advance the cursor until we reach the right screen column.
last_vcol = 0;
- ptr = (char_u *)get_cursor_line_ptr();
+ ptr = get_cursor_line_ptr();
chartabsize_T cts;
- init_chartabsize_arg(&cts, curwin, 0, 0, (char *)ptr, (char *)ptr);
+ init_chartabsize_arg(&cts, curwin, 0, 0, ptr, ptr);
while (cts.cts_vcol <= (int)curwin->w_virtcol) {
last_vcol = cts.cts_vcol;
if (cts.cts_vcol > 0) {
@@ -1683,7 +1682,7 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
ptr = xmallocz(i);
memset(ptr, ' ', i);
new_cursor_col += (int)i;
- ins_str((char *)ptr);
+ ins_str(ptr);
xfree(ptr);
}
@@ -2062,8 +2061,8 @@ void insertchar(int c, int flags, int second_indent)
// Need to remove existing (middle) comment leader and insert end
// comment leader. First, check what comment leader we can find.
- char_u *line = (char_u *)get_cursor_line_ptr();
- int i = get_leader_len((char *)line, &p, false, true);
+ char *line = get_cursor_line_ptr();
+ int i = get_leader_len(line, &p, false, true);
if (i > 0 && vim_strchr(p, COM_MIDDLE) != NULL) { // Just checking
// Skip middle-comment string
while (*p && p[-1] != ':') { // find end of middle flags
@@ -2304,11 +2303,11 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove)
// Save the inserted text for later redo with ^@ and CTRL-A.
// Don't do it when "restart_edit" was set and nothing was inserted,
// otherwise CTRL-O w and then <Left> will clear "last_insert".
- ptr = (char *)get_inserted();
+ ptr = get_inserted();
if (did_restart_edit == 0 || (ptr != NULL
&& (int)strlen(ptr) > new_insert_skip)) {
xfree(last_insert);
- last_insert = (char_u *)ptr;
+ last_insert = ptr;
last_insert_skip = new_insert_skip;
} else {
xfree(ptr);
@@ -2414,7 +2413,7 @@ static void stop_insert(pos_T *end_insert_pos, int esc, int nomove)
// Used for the replace command.
void set_last_insert(int c)
{
- char_u *s;
+ char *s;
xfree(last_insert);
last_insert = xmalloc(MB_MAXBYTES * 3 + 5);
@@ -2423,7 +2422,7 @@ void set_last_insert(int c)
if (c < ' ' || c == DEL) {
*s++ = Ctrl_V;
}
- s = add_char2buf(c, s);
+ s = (char *)add_char2buf(c, (char_u *)s);
*s++ = ESC;
*s++ = NUL;
last_insert_skip = 0;
@@ -2738,12 +2737,12 @@ char_u *get_last_insert(void)
if (last_insert == NULL) {
return NULL;
}
- return last_insert + last_insert_skip;
+ return (char_u *)last_insert + last_insert_skip;
}
// Get last inserted string, and remove trailing <Esc>.
// Returns pointer to allocated memory (must be freed) or NULL.
-char_u *get_last_insert_save(void)
+char *get_last_insert_save(void)
{
char *s;
int len;
@@ -2751,13 +2750,13 @@ char_u *get_last_insert_save(void)
if (last_insert == NULL) {
return NULL;
}
- s = xstrdup((char *)last_insert + last_insert_skip);
+ s = xstrdup(last_insert + last_insert_skip);
len = (int)strlen(s);
if (len > 0 && s[len - 1] == ESC) { // remove trailing ESC
s[len - 1] = NUL;
}
- return (char_u *)s;
+ return s;
}
/// Check the word in front of the cursor for an abbreviation.
@@ -3127,7 +3126,7 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty)
// make up some named keys <o>, <O>, <e>, <0>, <>>, <<>, <*>,
// <:> and <!> so that people can re-indent on o, O, e, 0, <,
// >, *, : and ! keys if they really really want to.
- if (vim_strchr("<>!*oOe0:", look[1]) != NULL
+ if (vim_strchr("<>!*oOe0:", (uint8_t)look[1]) != NULL
&& keytyped == look[1]) {
return true;
}
@@ -3182,7 +3181,7 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty)
// TODO(@brammool): multi-byte
if (keytyped == (int)(uint8_t)p[-1]
|| (icase && keytyped < 256
- && TOLOWER_LOC(keytyped) == TOLOWER_LOC((int)p[-1]))) {
+ && TOLOWER_LOC(keytyped) == TOLOWER_LOC((uint8_t)p[-1]))) {
line = get_cursor_pos_ptr();
assert(p >= look && (uintmax_t)(p - look) <= SIZE_MAX);
if ((curwin->w_cursor.col == (colnr_T)(p - look)
@@ -3475,7 +3474,7 @@ static void ins_ctrl_hat(void)
State |= MODE_LANGMAP;
}
}
- set_iminsert_global();
+ set_iminsert_global(curbuf);
showmode();
// Show/unshow value of 'keymap' in status lines.
status_redraw_curbuf();
@@ -3661,8 +3660,7 @@ static bool ins_start_select(int c)
static void ins_insert(int replaceState)
{
set_vim_var_string(VV_INSERTMODE, ((State & REPLACE_FLAG) ? "i" :
- replaceState == MODE_VREPLACE ? "v" :
- "r"), 1);
+ replaceState == MODE_VREPLACE ? "v" : "r"), 1);
ins_apply_autocmds(EVENT_INSERTCHANGE);
if (State & REPLACE_FLAG) {
State = MODE_INSERT | (State & MODE_LANGMAP);
@@ -4503,7 +4501,7 @@ static bool ins_tab(void)
if (!curbuf->b_p_et && (tabstop_count(curbuf->b_p_vsts_array) > 0
|| get_sts_value() > 0
|| (p_sta && ind))) {
- char_u *ptr;
+ char *ptr;
char *saved_line = NULL; // init for GCC
pos_T pos;
pos_T fpos;
@@ -4518,9 +4516,9 @@ static bool ins_tab(void)
pos = curwin->w_cursor;
cursor = &pos;
saved_line = xstrdup(get_cursor_line_ptr());
- ptr = (char_u *)saved_line + pos.col;
+ ptr = saved_line + pos.col;
} else {
- ptr = (char_u *)get_cursor_pos_ptr();
+ ptr = get_cursor_pos_ptr();
cursor = &curwin->w_cursor;
}
@@ -4548,9 +4546,9 @@ static bool ins_tab(void)
getvcol(curwin, &fpos, &vcol, NULL, NULL);
getvcol(curwin, cursor, &want_vcol, NULL, NULL);
- char_u *tab = (char_u *)"\t";
+ char *tab = "\t";
chartabsize_T cts;
- init_chartabsize_arg(&cts, curwin, 0, vcol, (char *)tab, (char *)tab);
+ init_chartabsize_arg(&cts, curwin, 0, vcol, tab, tab);
// Use as many TABs as possible. Beware of 'breakindent', 'showbreak'
// and 'linebreak' adding extra virtual columns.
@@ -4579,13 +4577,13 @@ static bool ins_tab(void)
if (change_col >= 0) {
int repl_off = 0;
// Skip over the spaces we need.
- init_chartabsize_arg(&cts, curwin, 0, vcol, (char *)ptr, (char *)ptr);
+ init_chartabsize_arg(&cts, curwin, 0, vcol, ptr, ptr);
while (cts.cts_vcol < want_vcol && *cts.cts_ptr == ' ') {
cts.cts_vcol += lbr_chartabsize(&cts);
cts.cts_ptr++;
repl_off++;
}
- ptr = (char_u *)cts.cts_ptr;
+ ptr = cts.cts_ptr;
vcol = cts.cts_vcol;
clear_chartabsize_arg(&cts);
@@ -4762,8 +4760,8 @@ static int ins_digraph(void)
int ins_copychar(linenr_T lnum)
{
int c;
- char_u *ptr, *prev_ptr;
- char_u *line;
+ char *ptr, *prev_ptr;
+ char *line;
if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) {
vim_beep(BO_COPY);
@@ -4771,25 +4769,25 @@ int ins_copychar(linenr_T lnum)
}
// try to advance to the cursor column
- line = (char_u *)ml_get(lnum);
+ line = ml_get(lnum);
prev_ptr = line;
validate_virtcol();
chartabsize_T cts;
- init_chartabsize_arg(&cts, curwin, lnum, 0, (char *)line, (char *)line);
+ init_chartabsize_arg(&cts, curwin, lnum, 0, line, line);
while (cts.cts_vcol < curwin->w_virtcol && *cts.cts_ptr != NUL) {
- prev_ptr = (char_u *)cts.cts_ptr;
+ prev_ptr = cts.cts_ptr;
cts.cts_vcol += lbr_chartabsize_adv(&cts);
}
if (cts.cts_vcol > curwin->w_virtcol) {
ptr = prev_ptr;
} else {
- ptr = (char_u *)cts.cts_ptr;
+ ptr = cts.cts_ptr;
}
clear_chartabsize_arg(&cts);
- c = utf_ptr2char((char *)ptr);
+ c = utf_ptr2char(ptr);
if (c == NUL) {
vim_beep(BO_COPY);
}
@@ -4838,7 +4836,7 @@ static int ins_ctrl_ey(int tc)
static void ins_try_si(int c)
{
pos_T *pos, old_pos;
- char_u *ptr;
+ char *ptr;
int i;
bool temp;
@@ -4852,7 +4850,7 @@ static void ins_try_si(int c)
// containing the matching '(' if there is one. This handles the
// case where an "if (..\n..) {" statement continues over multiple
// lines -- webb
- ptr = (char_u *)ml_get(pos->lnum);
+ ptr = ml_get(pos->lnum);
i = pos->col;
if (i > 0) { // skip blanks before '{'
while (--i > 0 && ascii_iswhite(ptr[i])) {}
@@ -4877,7 +4875,7 @@ static void ins_try_si(int c)
old_pos = curwin->w_cursor;
i = get_indent();
while (curwin->w_cursor.lnum > 1) {
- ptr = (char_u *)skipwhite(ml_get(--(curwin->w_cursor.lnum)));
+ ptr = skipwhite(ml_get(--(curwin->w_cursor.lnum)));
// ignore empty lines and lines starting with '#'.
if (*ptr != '#' && *ptr != NUL) {
@@ -4928,7 +4926,7 @@ colnr_T get_nolist_virtcol(void)
// "c" is the character that was typed.
// Return a pointer to allocated memory with the replacement string.
// Return NULL to continue inserting "c".
-static char_u *do_insert_char_pre(int c)
+static char *do_insert_char_pre(int c)
{
char buf[MB_MAXBYTES + 1];
const int save_State = State;
@@ -4959,7 +4957,7 @@ static char_u *do_insert_char_pre(int c)
// Restore the State, it may have been changed.
State = save_State;
- return (char_u *)res;
+ return res;
}
bool get_can_cindent(void)
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index f9825496a5..4392ea306f 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -268,7 +268,7 @@ static struct vimvar {
VV(VV__NULL_BLOB, "_null_blob", VAR_BLOB, VV_RO),
VV(VV_LUA, "lua", VAR_PARTIAL, VV_RO),
VV(VV_RELNUM, "relnum", VAR_NUMBER, VV_RO),
- VV(VV_WRAP, "wrap", VAR_BOOL, VV_RO),
+ VV(VV_VIRTNUM, "virtnum", VAR_NUMBER, VV_RO),
};
#undef VV
@@ -1485,9 +1485,9 @@ char *get_lval(char *const name, typval_T *const rettv, lval_T *const lp, const
tv_clear(&var1);
break;
// existing variable, need to check if it can be changed
- } else if (!(flags & GLV_READ_ONLY) && var_check_ro(lp->ll_di->di_flags,
- (const char *)name,
- (size_t)(p - name))) {
+ } else if (!(flags & GLV_READ_ONLY)
+ && (var_check_ro(lp->ll_di->di_flags, name, (size_t)(p - name))
+ || var_check_lock(lp->ll_di->di_flags, name, (size_t)(p - name)))) {
tv_clear(&var1);
return NULL;
}
@@ -1618,7 +1618,7 @@ void set_var_lval(lval_T *lp, char *endp, typval_T *rettv, int copy, const bool
semsg(_(e_letwrong), op);
return;
}
- if (var_check_lock(lp->ll_blob->bv_lock, lp->ll_name, TV_CSTRING)) {
+ if (value_check_lock(lp->ll_blob->bv_lock, lp->ll_name, TV_CSTRING)) {
return;
}
@@ -1648,7 +1648,7 @@ void set_var_lval(lval_T *lp, char *endp, typval_T *rettv, int copy, const bool
// the end is an error otherwise.
if (lp->ll_n1 < gap->ga_len || lp->ll_n1 == gap->ga_len) {
ga_grow(&lp->ll_blob->bv_ga, 1);
- tv_blob_set(lp->ll_blob, (int)lp->ll_n1, (char_u)val);
+ tv_blob_set(lp->ll_blob, (int)lp->ll_n1, (uint8_t)val);
if (lp->ll_n1 == gap->ga_len) {
gap->ga_len++;
}
@@ -1681,10 +1681,10 @@ void set_var_lval(lval_T *lp, char *endp, typval_T *rettv, int copy, const bool
set_var_const(lp->ll_name, lp->ll_name_len, rettv, copy, is_const);
}
*endp = (char)cc;
- } else if (var_check_lock(lp->ll_newkey == NULL
- ? lp->ll_tv->v_lock
- : lp->ll_tv->vval.v_dict->dv_lock,
- lp->ll_name, TV_CSTRING)) {
+ } else if (value_check_lock(lp->ll_newkey == NULL
+ ? lp->ll_tv->v_lock
+ : lp->ll_tv->vval.v_dict->dv_lock,
+ lp->ll_name, TV_CSTRING)) {
// Skip
} else if (lp->ll_range) {
listitem_T *ll_li = lp->ll_li;
@@ -1698,8 +1698,8 @@ void set_var_lval(lval_T *lp, char *endp, typval_T *rettv, int copy, const bool
// Check whether any of the list items is locked
for (ri = tv_list_first(rettv->vval.v_list);
ri != NULL && ll_li != NULL;) {
- if (var_check_lock(TV_LIST_ITEM_TV(ll_li)->v_lock, lp->ll_name,
- TV_CSTRING)) {
+ if (value_check_lock(TV_LIST_ITEM_TV(ll_li)->v_lock, lp->ll_name,
+ TV_CSTRING)) {
return;
}
ri = TV_LIST_ITEM_NEXT(rettv->vval.v_list, ri);
@@ -2185,7 +2185,7 @@ int pattern_match(const char *pat, const char *text, bool ic)
regmatch.regprog = vim_regcomp((char *)pat, RE_MAGIC + RE_STRING);
if (regmatch.regprog != NULL) {
regmatch.rm_ic = ic;
- matches = vim_regexec_nl(&regmatch, (char_u *)text, (colnr_T)0);
+ matches = vim_regexec_nl(&regmatch, (char *)text, (colnr_T)0);
vim_regfree(regmatch.regprog);
}
p_cpo = save_cpo;
@@ -2543,7 +2543,7 @@ static int eval4(char **arg, typval_T *rettv, int evaluate)
if (p[2] == 'n' && p[3] == 'o' && p[4] == 't') {
len = 5;
}
- if (!isalnum(p[len]) && p[len] != '_') {
+ if (!isalnum((uint8_t)p[len]) && p[len] != '_') {
type = len == 2 ? EXPR_IS : EXPR_ISNOT;
}
}
@@ -2660,10 +2660,10 @@ static int eval5(char **arg, typval_T *rettv, int evaluate)
blob_T *const b = tv_blob_alloc();
for (int i = 0; i < tv_blob_len(b1); i++) {
- ga_append(&b->bv_ga, (char)tv_blob_get(b1, i));
+ ga_append(&b->bv_ga, tv_blob_get(b1, i));
}
for (int i = 0; i < tv_blob_len(b2); i++) {
- ga_append(&b->bv_ga, (char)tv_blob_get(b2, i));
+ ga_append(&b->bv_ga, tv_blob_get(b2, i));
}
tv_clear(rettv);
@@ -2887,12 +2887,7 @@ static int eval6(char **arg, typval_T *rettv, int evaluate, int want_string)
/// @return OK or FAIL.
static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
{
- varnumber_T n;
- int len;
- char *s;
- const char *start_leader, *end_leader;
int ret = OK;
- char *alias;
static int recurse = 0;
// Initialise variable so that tv_clear() can't mistake this for a
@@ -2900,11 +2895,11 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
rettv->v_type = VAR_UNKNOWN;
// Skip '!', '-' and '+' characters. They are handled later.
- start_leader = *arg;
+ const char *start_leader = *arg;
while (**arg == '!' || **arg == '-' || **arg == '+') {
*arg = skipwhite(*arg + 1);
}
- end_leader = *arg;
+ const char *end_leader = *arg;
// Limit recursion to 1000 levels. At least at 10000 we run out of stack
// and crash. With MSVC the stack is smaller.
@@ -2931,88 +2926,9 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
case '6':
case '7':
case '8':
- case '9': {
- char *p = skipdigits(*arg + 1);
- int get_float = false;
-
- // We accept a float when the format matches
- // "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very
- // strict to avoid backwards compatibility problems.
- // Don't look for a float after the "." operator, so that
- // ":let vers = 1.2.3" doesn't fail.
- if (!want_string && p[0] == '.' && ascii_isdigit(p[1])) {
- get_float = true;
- p = skipdigits(p + 2);
- if (*p == 'e' || *p == 'E') {
- p++;
- if (*p == '-' || *p == '+') {
- p++;
- }
- if (!ascii_isdigit(*p)) {
- get_float = false;
- } else {
- p = skipdigits(p + 1);
- }
- }
- if (ASCII_ISALPHA(*p) || *p == '.') {
- get_float = false;
- }
- }
- if (get_float) {
- float_T f;
-
- *arg += string2float(*arg, &f);
- if (evaluate) {
- rettv->v_type = VAR_FLOAT;
- rettv->vval.v_float = f;
- }
- } else if (**arg == '0' && ((*arg)[1] == 'z' || (*arg)[1] == 'Z')) {
- blob_T *blob = NULL;
- // Blob constant: 0z0123456789abcdef
- if (evaluate) {
- blob = tv_blob_alloc();
- }
- char *bp;
- for (bp = *arg + 2; ascii_isxdigit(bp[0]); bp += 2) {
- if (!ascii_isxdigit(bp[1])) {
- if (blob != NULL) {
- emsg(_("E973: Blob literal should have an even number of hex "
- "characters"));
- ga_clear(&blob->bv_ga);
- XFREE_CLEAR(blob);
- }
- ret = FAIL;
- break;
- }
- if (blob != NULL) {
- ga_append(&blob->bv_ga, (char)((hex2nr(*bp) << 4) + hex2nr(*(bp + 1))));
- }
- if (bp[2] == '.' && ascii_isxdigit(bp[3])) {
- bp++;
- }
- }
- if (blob != NULL) {
- tv_blob_set_ret(rettv, blob);
- }
- *arg = bp;
- } else {
- // decimal, hex or octal number
- vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0, true);
- if (len == 0) {
- if (evaluate) {
- semsg(_(e_invexpr2), *arg);
- }
- ret = FAIL;
- break;
- }
- *arg += len;
- if (evaluate) {
- rettv->v_type = VAR_NUMBER;
- rettv->vval.v_number = n;
- }
- }
+ case '9':
+ ret = get_number_tv(arg, rettv, evaluate, want_string);
break;
- }
// String constant: "string".
case '"':
@@ -3090,8 +3006,9 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
if (ret == NOTDONE) {
// Must be a variable or function name.
// Can also be a curly-braces kind of name: {expr}.
- s = *arg;
- len = get_name_len((const char **)arg, &alias, evaluate, true);
+ char *s = *arg;
+ char *alias;
+ int len = get_name_len((const char **)arg, &alias, evaluate, true);
if (alias != NULL) {
s = alias;
}
@@ -3716,6 +3633,91 @@ int get_option_tv(const char **const arg, typval_T *const rettv, const bool eval
return ret;
}
+/// Allocate a variable for a number constant. Also deals with "0z" for blob.
+///
+/// @return OK or FAIL.
+static int get_number_tv(char **arg, typval_T *rettv, bool evaluate, bool want_string)
+{
+ char *p = skipdigits(*arg + 1);
+ bool get_float = false;
+
+ // We accept a float when the format matches
+ // "[0-9]\+\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?". This is very
+ // strict to avoid backwards compatibility problems.
+ // Don't look for a float after the "." operator, so that
+ // ":let vers = 1.2.3" doesn't fail.
+ if (!want_string && p[0] == '.' && ascii_isdigit(p[1])) {
+ get_float = true;
+ p = skipdigits(p + 2);
+ if (*p == 'e' || *p == 'E') {
+ p++;
+ if (*p == '-' || *p == '+') {
+ p++;
+ }
+ if (!ascii_isdigit(*p)) {
+ get_float = false;
+ } else {
+ p = skipdigits(p + 1);
+ }
+ }
+ if (ASCII_ISALPHA(*p) || *p == '.') {
+ get_float = false;
+ }
+ }
+ if (get_float) {
+ float_T f;
+ *arg += string2float(*arg, &f);
+ if (evaluate) {
+ rettv->v_type = VAR_FLOAT;
+ rettv->vval.v_float = f;
+ }
+ } else if (**arg == '0' && ((*arg)[1] == 'z' || (*arg)[1] == 'Z')) {
+ // Blob constant: 0z0123456789abcdef
+ blob_T *blob = NULL;
+ if (evaluate) {
+ blob = tv_blob_alloc();
+ }
+ char *bp;
+ for (bp = *arg + 2; ascii_isxdigit(bp[0]); bp += 2) {
+ if (!ascii_isxdigit(bp[1])) {
+ if (blob != NULL) {
+ emsg(_("E973: Blob literal should have an even number of hex characters"));
+ ga_clear(&blob->bv_ga);
+ XFREE_CLEAR(blob);
+ }
+ return FAIL;
+ }
+ if (blob != NULL) {
+ ga_append(&blob->bv_ga, (uint8_t)((hex2nr(*bp) << 4) + hex2nr(*(bp + 1))));
+ }
+ if (bp[2] == '.' && ascii_isxdigit(bp[3])) {
+ bp++;
+ }
+ }
+ if (blob != NULL) {
+ tv_blob_set_ret(rettv, blob);
+ }
+ *arg = bp;
+ } else {
+ // decimal, hex or octal number
+ int len;
+ varnumber_T n;
+ vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0, true);
+ if (len == 0) {
+ if (evaluate) {
+ semsg(_(e_invexpr2), *arg);
+ }
+ return FAIL;
+ }
+ *arg += len;
+ if (evaluate) {
+ rettv->v_type = VAR_NUMBER;
+ rettv->vval.v_number = n;
+ }
+ }
+ return OK;
+}
+
/// Allocate a variable for a string constant.
///
/// @return OK or FAIL.
@@ -3777,7 +3779,7 @@ static int get_string_tv(char **arg, typval_T *rettv, int evaluate)
case 'U':
if (ascii_isxdigit(p[1])) {
int n, nr;
- int c = toupper(*p);
+ int c = toupper((uint8_t)(*p));
if (c == 'X') {
n = 2;
@@ -3828,7 +3830,7 @@ static int get_string_tv(char **arg, typval_T *rettv, int evaluate)
if (p[1] != '*') {
flags |= FSK_SIMPLIFY;
}
- extra = trans_special((const char **)&p, strlen(p), (char_u *)name, flags, false, NULL);
+ extra = trans_special((const char **)&p, strlen(p), name, flags, false, NULL);
if (extra != 0) {
name += extra;
if (name >= rettv->vval.v_string + len) {
@@ -3924,7 +3926,7 @@ static void partial_free(partial_T *pt)
xfree(pt->pt_argv);
tv_dict_unref(pt->pt_dict);
if (pt->pt_name != NULL) {
- func_unref((char_u *)pt->pt_name);
+ func_unref(pt->pt_name);
xfree(pt->pt_name);
} else {
func_ptr_unref(pt->pt_func);
@@ -4490,7 +4492,7 @@ bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack, list_stack
// A partial does not have a copyID, because it cannot contain itself.
if (pt != NULL) {
- abort = set_ref_in_func((char_u *)pt->pt_name, pt->pt_func, copyID);
+ abort = set_ref_in_func(pt->pt_name, pt->pt_func, copyID);
if (pt->pt_dict != NULL) {
typval_T dtv;
@@ -4507,7 +4509,7 @@ bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack, list_stack
break;
}
case VAR_FUNC:
- abort = set_ref_in_func((char_u *)tv->vval.v_string, NULL, copyID);
+ abort = set_ref_in_func(tv->vval.v_string, NULL, copyID);
break;
case VAR_UNKNOWN:
case VAR_BOOL:
@@ -4795,12 +4797,12 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map)
} else if (argvars[0].v_type == VAR_LIST) {
if ((l = argvars[0].vval.v_list) == NULL
|| (!map
- && var_check_lock(tv_list_locked(l), arg_errmsg, TV_TRANSLATE))) {
+ && value_check_lock(tv_list_locked(l), arg_errmsg, TV_TRANSLATE))) {
return;
}
} else if (argvars[0].v_type == VAR_DICT) {
if ((d = argvars[0].vval.v_dict) == NULL
- || (!map && var_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE))) {
+ || (!map && value_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE))) {
return;
}
} else {
@@ -4839,7 +4841,7 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map)
dictitem_T *di = TV_DICT_HI2DI(hi);
if (map
- && (var_check_lock(di->di_tv.v_lock, arg_errmsg, TV_TRANSLATE)
+ && (value_check_lock(di->di_tv.v_lock, arg_errmsg, TV_TRANSLATE)
|| var_check_ro(di->di_flags, arg_errmsg, TV_TRANSLATE))) {
break;
}
@@ -4879,7 +4881,7 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map)
}
if (map) {
if (tv.vval.v_number != val) {
- tv_blob_set(b, i, (char_u)tv.vval.v_number);
+ tv_blob_set(b, i, (uint8_t)tv.vval.v_number);
}
} else if (rem) {
char *const p = argvars[0].vval.v_blob->bv_ga.ga_data;
@@ -4899,8 +4901,8 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map)
}
for (listitem_T *li = tv_list_first(l); li != NULL;) {
if (map
- && var_check_lock(TV_LIST_ITEM_TV(li)->v_lock, arg_errmsg,
- TV_TRANSLATE)) {
+ && value_check_lock(TV_LIST_ITEM_TV(li)->v_lock, arg_errmsg,
+ TV_TRANSLATE)) {
break;
}
vimvars[VV_KEY].vv_nr = idx;
@@ -5000,7 +5002,7 @@ void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref)
// Don't check an autoload name for existence here.
} else if (trans_name != NULL
&& (is_funcref
- ? find_func((char_u *)trans_name) == NULL
+ ? find_func(trans_name) == NULL
: !translated_function_exists((const char *)trans_name))) {
semsg(_("E700: Unknown function: %s"), s);
} else {
@@ -5099,12 +5101,12 @@ void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref)
func_ptr_ref(pt->pt_func);
xfree(name);
} else if (is_funcref) {
- pt->pt_func = find_func((char_u *)trans_name);
+ pt->pt_func = find_func(trans_name);
func_ptr_ref(pt->pt_func);
xfree(name);
} else {
pt->pt_name = name;
- func_ref((char_u *)name);
+ func_ref(name);
}
rettv->v_type = VAR_PARTIAL;
@@ -5113,7 +5115,7 @@ void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref)
// result is a VAR_FUNC
rettv->v_type = VAR_FUNC;
rettv->vval.v_string = name;
- func_ref((char_u *)name);
+ func_ref(name);
}
}
theend:
@@ -5529,12 +5531,12 @@ bool callback_from_typval(Callback *const callback, const typval_T *const arg)
if (callback->data.funcref == NULL) {
callback->data.funcref = xstrdup(name);
}
- func_ref((char_u *)callback->data.funcref);
+ func_ref(callback->data.funcref);
callback->type = kCallbackFuncref;
}
} else if (nlua_is_table_from_lua(arg)) {
// TODO(tjdvries): UnifiedCallback
- char *name = (char *)nlua_register_table_as_callable(arg);
+ char *name = nlua_register_table_as_callable(arg);
if (name != NULL) {
callback->data.funcref = xstrdup(name);
@@ -6302,7 +6304,7 @@ int get_id_len(const char **const arg)
// slice "[n:]". Also "xx:" is not a namespace.
len = (int)(p - *arg);
if (len > 1
- || (len == 1 && vim_strchr(namespace_char, **arg) == NULL)) {
+ || (len == 1 && vim_strchr(namespace_char, (uint8_t)(**arg)) == NULL)) {
break;
}
}
@@ -6430,7 +6432,7 @@ const char *find_name_end(const char *arg, const char **expr_start, const char *
// slice "[n:]". Also "xx:" is not a namespace. But {ns}: is.
len = (int)(p - arg);
if ((len > 1 && p[-1] != '}')
- || (len == 1 && vim_strchr(namespace_char, *arg) == NULL)) {
+ || (len == 1 && vim_strchr(namespace_char, (uint8_t)(*arg)) == NULL)) {
break;
}
}
@@ -7408,7 +7410,7 @@ void ex_echo(exarg_T *eap)
/// ":echohl {name}".
void ex_echohl(exarg_T *eap)
{
- echo_attr = syn_name2attr((char_u *)eap->arg);
+ echo_attr = syn_name2attr(eap->arg);
}
/// ":execute expr1 ..." execute the result of an expression.
@@ -8081,7 +8083,7 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, const char
if (regmatch.regprog != NULL) {
char *tail = str;
char *end = str + strlen(str);
- while (vim_regexec_nl(&regmatch, (char_u *)str, (colnr_T)(tail - str))) {
+ while (vim_regexec_nl(&regmatch, str, (colnr_T)(tail - str))) {
// Skip empty match except for first match.
if (regmatch.startp[0] == regmatch.endp[0]) {
if (zero_width == regmatch.startp[0]) {
@@ -8100,7 +8102,7 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, const char
// - The text up to where the match is.
// - The substituted text.
// - The text after the match.
- sublen = vim_regsub(&regmatch, (char_u *)sub, expr, (char_u *)tail, 0, REGSUB_MAGIC);
+ sublen = vim_regsub(&regmatch, sub, expr, tail, 0, REGSUB_MAGIC);
ga_grow(&ga, (int)((end - tail) + sublen -
(regmatch.endp[0] - regmatch.startp[0])));
@@ -8108,8 +8110,8 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, const char
int i = (int)(regmatch.startp[0] - tail);
memmove((char_u *)ga.ga_data + ga.ga_len, tail, (size_t)i);
// add the substituted text
- (void)vim_regsub(&regmatch, (char_u *)sub, expr,
- (char_u *)ga.ga_data + ga.ga_len + i, sublen,
+ (void)vim_regsub(&regmatch, sub, expr,
+ (char *)ga.ga_data + ga.ga_len + i, sublen,
REGSUB_COPY | REGSUB_MAGIC);
ga.ga_len += i + sublen - 1;
tail = regmatch.endp[0];
@@ -8297,7 +8299,7 @@ bool eval_has_provider(const char *feat)
if (get_var_tv(buf, len, &tv, NULL, false, true) == FAIL) {
// Show a hint if Call() is defined but g:loaded_xx_provider is missing.
snprintf(buf, sizeof(buf), "provider#%s#Call", name);
- if (!!find_func((char_u *)buf) && p_lpl) {
+ if (!!find_func(buf) && p_lpl) {
semsg("provider: %s: missing required variable g:loaded_%s_provider",
name, name);
}
@@ -8312,7 +8314,7 @@ bool eval_has_provider(const char *feat)
if (ok) {
// Call() must be defined if provider claims to be working.
snprintf(buf, sizeof(buf), "provider#%s#Call", name);
- if (!find_func((char_u *)buf)) {
+ if (!find_func(buf)) {
semsg("provider: %s: g:loaded_%s_provider=2 but %s is not defined",
name, name, buf);
ok = false;
@@ -8335,10 +8337,10 @@ void eval_fmt_source_name_line(char *buf, size_t bufsize)
/// ":checkhealth [plugins]"
void ex_checkhealth(exarg_T *eap)
{
- bool found = !!find_func((char_u *)"health#check");
+ bool found = !!find_func("health#check");
if (!found
&& script_autoload("health#check", sizeof("health#check") - 1, false)) {
- found = !!find_func((char_u *)"health#check");
+ found = !!find_func("health#check");
}
if (!found) {
const char *vimruntime_env = os_getenv("VIMRUNTIME");
diff --git a/src/nvim/eval.h b/src/nvim/eval.h
index d67414f12f..86bc76e793 100644
--- a/src/nvim/eval.h
+++ b/src/nvim/eval.h
@@ -166,7 +166,7 @@ typedef enum {
VV__NULL_BLOB, // Blob with NULL value. For test purposes only.
VV_LUA,
VV_RELNUM,
- VV_WRAP,
+ VV_VIRTNUM,
} VimVarIndex;
/// All recognized msgpack types
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index 14be6aba73..9a5ab51c71 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -26,7 +26,7 @@ return {
acos={args=1, base=1, float_func="acos"}, -- WJMc
add={args=2, base=1},
['and']={args=2, base=1},
- api_info={},
+ api_info={fast=true},
append={args=2, base=2},
appendbufline={args=3, base=3},
argc={args={0, 1}},
@@ -64,14 +64,14 @@ return {
bufwinid={args=1, base=1},
bufwinnr={args=1, base=1},
byte2line={args=1, base=1},
- byteidx={args=2, base=1},
- byteidxcomp={args=2, base=1},
+ byteidx={args=2, base=1, fast=true},
+ byteidxcomp={args=2, base=1, fast=true},
call={args={2, 3}, base=1},
ceil={args=1, base=1, float_func="ceil"},
changenr={},
chanclose={args={1, 2}},
chansend={args=2},
- char2nr={args={1, 2}, base=1},
+ char2nr={args={1, 2}, base=1, fast=true},
charclass={args=1, base=1},
charcol={args={1, 2}, base=1},
charidx={args={2, 3}, base=1},
@@ -100,7 +100,7 @@ return {
deletebufline={args={2,3}, base=1},
dictwatcheradd={args=3},
dictwatcherdel={args=3},
- did_filetype={},
+ did_filetype={fast=true},
diff_filler={args=1, base=1},
diff_hlID={args=2, base=1},
digraph_get={args=1, base=1},
@@ -108,11 +108,11 @@ return {
digraph_set={args=2, base=1},
digraph_setlist={args=1, base=1},
empty={args=1, base=1},
- environ={},
- escape={args=2, base=1},
+ environ={fast=true},
+ escape={args=2, base=1, fast=true},
eval={args=1, base=1},
eventhandler={},
- executable={args=1, base=1},
+ executable={args=1, base=1, fast=true},
execute={args={1, 2}, base=1},
exepath={args=1, base=1},
exists={args=1, base=1},
@@ -122,8 +122,8 @@ return {
extend={args={2, 3}, base=1},
feedkeys={args={1, 2}, base=1},
file_readable={args=1, base=1, func='f_filereadable'}, -- obsolete
- filereadable={args=1, base=1},
- filewritable={args=1, base=1},
+ filereadable={args=1, base=1, fast=true},
+ filewritable={args=1, base=1, fast=true},
filter={args=2, base=1},
finddir={args={1, 3}, base=1},
findfile={args={1, 3}, base=1},
@@ -131,8 +131,8 @@ return {
float2nr={args=1, base=1},
floor={args=1, base=1, float_func="floor"},
fmod={args=2, base=1},
- fnameescape={args=1, base=1},
- fnamemodify={args=2, base=1},
+ fnameescape={args=1, base=1, fast=true},
+ fnamemodify={args=2, base=1, fast=true},
foldclosed={args=1, base=1},
foldclosedend={args=1, base=1},
foldlevel={args=1, base=1},
@@ -148,6 +148,7 @@ return {
getbufline={args={2, 3}, base=1},
getbufoneline={args=2, base=1},
getbufvar={args={2, 3}, base=1},
+ getcellwidths={},
getchangelist={args={0, 1}, base=1},
getchar={args={0, 1}},
getcharmod={},
@@ -166,17 +167,17 @@ return {
getcwd={args={0, 2}, base=1},
getenv={args=1, base=1},
getfontname={args={0, 1}},
- getfperm={args=1, base=1},
- getfsize={args=1, base=1},
- getftime={args=1, base=1},
- getftype={args=1, base=1},
+ getfperm={args=1, base=1, fast=true},
+ getfsize={args=1, base=1, fast=true},
+ getftime={args=1, base=1, fast=true},
+ getftype={args=1, base=1, fast=true},
getjumplist={args={0, 2}, base=1},
getline={args={1, 2}, base=1},
getloclist={args={1, 2}},
getmarklist={args={0, 1}, base=1},
getmatches={args={0, 1}},
getmousepos={},
- getpid={},
+ getpid={fast=true},
getpos={args=1, base=1},
getqflist={args={0, 1}},
getreg={args={0, 3}, base=1},
@@ -207,7 +208,7 @@ return {
histnr={args=1, base=1},
hlID={args=1, base=1},
hlexists={args=1, base=1},
- hostname={},
+ hostname={fast=true},
iconv={args=3, base=1, fast=true},
indent={args=1, base=1},
index={args={2, 4}, base=1},
@@ -220,7 +221,7 @@ return {
insert={args={2, 3}, base=1},
interrupt={args=0},
invert={args=1, base=1},
- isdirectory={args=1, base=1},
+ isdirectory={args=1, base=1, fast=true},
isinf={args=1, base=1},
islocked={args=1, base=1},
isnan={args=1, base=1},
@@ -299,13 +300,13 @@ return {
reg_executing={},
reg_recording={},
reg_recorded={},
- reltime={args={0, 2}, base=1},
- reltimefloat={args=1, base=1},
- reltimestr={args=1, base=1},
+ reltime={args={0, 2}, base=1, fast=true},
+ reltimefloat={args=1, base=1, fast=true},
+ reltimestr={args=1, base=1, fast=true},
remove={args={2, 3}, base=1},
rename={args=2, base=1},
- ['repeat']={args=2, base=1},
- resolve={args=1, base=1},
+ ['repeat']={args=2, base=1, fast=true},
+ resolve={args=1, base=1, fast=true},
reverse={args=1, base=1},
round={args=1, base=1, float_func="round"},
rpcnotify={args=varargs(2)},
@@ -373,24 +374,24 @@ return {
split={args={1, 3}, base=1},
sqrt={args=1, base=1, float_func="sqrt"},
srand={args={0, 1}, base=1},
- stdpath={args=1},
+ stdpath={args=1, fast=true},
str2float={args=1, base=1},
str2list={args={1, 2}, base=1},
str2nr={args={1, 3}, base=1},
strcharlen={args=1, base=1},
- strcharpart={args={2, 3}, base=1},
+ strcharpart={args={2, 3}, base=1, fast=true},
strchars={args={1, 2}, base=1},
strdisplaywidth={args={1, 2}, base=1},
strftime={args={1, 2}, base=1},
strgetchar={args=2, base=1},
- stridx={args={2, 3}, base=1},
+ stridx={args={2, 3}, base=1, fast=true},
string={args=1, base=1},
strlen={args=1, base=1},
- strpart={args={2, 4}, base=1},
+ strpart={args={2, 4}, base=1, fast=true},
strptime={args=2, base=1},
strridx={args={2, 3}, base=1},
- strtrans={args=1, base=1},
- strwidth={args=1, base=1},
+ strtrans={args=1, base=1, fast=true},
+ strwidth={args=1, base=1, fast=true},
submatch={args={1, 2}, base=1},
substitute={args=4, base=1},
swapinfo={args=1, base=1},
@@ -418,12 +419,12 @@ return {
timer_start={args={2, 3}, base=1},
timer_stop={args=1, base=1},
timer_stopall={args=0},
- tolower={args=1, base=1},
- toupper={args=1, base=1},
+ tolower={args=1, base=1, fast=true},
+ toupper={args=1, base=1, fast=true},
tr={args=3, base=1},
trim={args={1, 3}, base=1},
trunc={args=1, base=1, float_func="trunc"},
- type={args=1, base=1},
+ type={args=1, base=1, fast=true},
undofile={args=1, base=1},
undotree={},
uniq={args={1, 3}, base=1},
@@ -446,7 +447,7 @@ return {
win_splitmove={args={2, 3}, base=1},
winbufnr={args=1, base=1},
wincol={},
- windowsversion={},
+ windowsversion={fast=true},
winheight={args=1, base=1},
winlayout={args={0, 1}, base=1},
winline={},
diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c
index 72eb0f8d67..2f37d1ba2e 100644
--- a/src/nvim/eval/buffer.c
+++ b/src/nvim/eval/buffer.c
@@ -9,6 +9,7 @@
#include "nvim/ascii.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/change.h"
#include "nvim/cursor.h"
#include "nvim/eval.h"
@@ -277,9 +278,9 @@ void f_appendbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
/// "bufadd(expr)" function
void f_bufadd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- char_u *name = (char_u *)tv_get_string(&argvars[0]);
+ char *name = (char *)tv_get_string(&argvars[0]);
- rettv->vval.v_number = buflist_add(*name == NUL ? NULL : (char *)name, 0);
+ rettv->vval.v_number = buflist_add(*name == NUL ? NULL : name, 0);
}
/// "bufexists(expr)" function
diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c
index 03d4862550..c2f1eae8af 100644
--- a/src/nvim/eval/encode.c
+++ b/src/nvim/eval/encode.c
@@ -309,7 +309,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
if (buf_[i_] == '\'') { \
ga_append(gap, '\''); \
} \
- ga_append(gap, buf_[i_]); \
+ ga_append(gap, (uint8_t)buf_[i_]); \
} \
ga_append(gap, '\''); \
} \
diff --git a/src/nvim/eval/encode.h b/src/nvim/eval/encode.h
index e66dab1cff..41e7614fc0 100644
--- a/src/nvim/eval/encode.h
+++ b/src/nvim/eval/encode.h
@@ -4,6 +4,7 @@
#include <msgpack.h>
#include <msgpack/pack.h>
#include <stddef.h>
+#include <string.h>
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c
index 86d6063b01..9caea2fef1 100644
--- a/src/nvim/eval/executor.c
+++ b/src/nvim/eval/executor.c
@@ -51,7 +51,7 @@ int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2, const char *cons
blob_T *const b1 = tv1->vval.v_blob;
blob_T *const b2 = tv2->vval.v_blob;
for (int i = 0; i < tv_blob_len(b2); i++) {
- ga_append(&b1->bv_ga, (char)tv_blob_get(b2, i));
+ ga_append(&b1->bv_ga, tv_blob_get(b2, i));
}
}
return OK;
@@ -69,7 +69,7 @@ int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2, const char *cons
if (tv2->v_type == VAR_LIST) {
break;
}
- if (vim_strchr("+-*/%", *op) != NULL) {
+ if (vim_strchr("+-*/%", (uint8_t)(*op)) != NULL) {
// nr += nr or nr -= nr, nr *= nr, nr /= nr, nr %= nr
varnumber_T n = tv_get_number(tv1);
if (tv2->v_type == VAR_FLOAT) {
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index d6b9ca20fc..48f3cd4293 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -244,11 +244,11 @@ int call_internal_func(const char *const fname, const int argcount, typval_T *co
}
/// Invoke a method for base->method().
-int call_internal_method(const char_u *const fname, const int argcount, typval_T *const argvars,
+int call_internal_method(const char *const fname, const int argcount, typval_T *const argvars,
typval_T *const rettv, typval_T *const basetv)
FUNC_ATTR_NONNULL_ALL
{
- const EvalFuncDef *const fdef = find_internal_func((const char *)fname);
+ const EvalFuncDef *const fdef = find_internal_func(fname);
if (fdef == NULL) {
return FCERR_UNKNOWN;
} else if (fdef->base_arg == BASE_NONE) {
@@ -362,20 +362,20 @@ static void f_add(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->vval.v_number = 1; // Default: failed.
if (argvars[0].v_type == VAR_LIST) {
list_T *const l = argvars[0].vval.v_list;
- if (!var_check_lock(tv_list_locked(l), N_("add() argument"),
- TV_TRANSLATE)) {
+ if (!value_check_lock(tv_list_locked(l), N_("add() argument"),
+ TV_TRANSLATE)) {
tv_list_append_tv(l, &argvars[1]);
tv_copy(&argvars[0], rettv);
}
} else if (argvars[0].v_type == VAR_BLOB) {
blob_T *const b = argvars[0].vval.v_blob;
if (b != NULL
- && !var_check_lock(b->bv_lock, N_("add() argument"), TV_TRANSLATE)) {
+ && !value_check_lock(b->bv_lock, N_("add() argument"), TV_TRANSLATE)) {
bool error = false;
const varnumber_T n = tv_get_number_chk(&argvars[1], &error);
if (!error) {
- ga_append(&b->bv_ga, (char)n);
+ ga_append(&b->bv_ga, (uint8_t)n);
tv_copy(&argvars[0], rettv);
}
}
@@ -557,7 +557,7 @@ static void f_call(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
func = partial_name(partial);
} else if (nlua_is_table_from_lua(&argvars[0])) {
// TODO(tjdevries): UnifiedCallback
- func = (char *)nlua_register_table_as_callable(&argvars[0]);
+ func = nlua_register_table_as_callable(&argvars[0]);
owned = true;
} else {
func = (char *)tv_get_string(&argvars[0]);
@@ -572,16 +572,16 @@ static void f_call(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (argvars[2].v_type != VAR_DICT) {
emsg(_(e_dictreq));
if (owned) {
- func_unref((char_u *)func);
+ func_unref(func);
}
return;
}
selfdict = argvars[2].vval.v_dict;
}
- func_call((char_u *)func, &argvars[1], partial, selfdict, rettv);
+ func_call(func, &argvars[1], partial, selfdict, rettv);
if (owned) {
- func_unref((char_u *)func);
+ func_unref(func);
}
}
@@ -1419,7 +1419,7 @@ static void f_diff_hlID(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
hlID = HLF_CHD; // Changed line.
}
}
- rettv->vval.v_number = hlID == (hlf_T)0 ? 0 : (int)(hlID + 1);
+ rettv->vval.v_number = hlID == (hlf_T)0 ? 0 : (hlID + 1);
}
/// "empty({expr})" function
@@ -1695,7 +1695,7 @@ static void f_exepath(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
#ifdef BACKSLASH_IN_FILENAME
if (path != NULL) {
- slash_adjust((char_u *)path);
+ slash_adjust(path);
}
#endif
@@ -1749,7 +1749,7 @@ static void f_expand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
int options = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND;
bool error = false;
#ifdef BACKSLASH_IN_FILENAME
- char_u *p_csl_save = p_csl;
+ char *p_csl_save = p_csl;
// avoid using 'completeslash' here
p_csl = empty_option;
@@ -1770,7 +1770,7 @@ static void f_expand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
size_t len;
char *errormsg = NULL;
- char *result = (char *)eval_vars((char_u *)s, (char_u *)s, &len, NULL, &errormsg, NULL, false);
+ char *result = eval_vars((char *)s, s, &len, NULL, &errormsg, NULL, false);
if (p_verbose == 0) {
emsg_off--;
} else if (errormsg != NULL) {
@@ -1896,9 +1896,9 @@ static void f_flatten(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
list_T *list = argvars[0].vval.v_list;
if (list != NULL
- && !var_check_lock(tv_list_locked(list),
- N_("flatten() argument"),
- TV_TRANSLATE)
+ && !value_check_lock(tv_list_locked(list),
+ N_("flatten() argument"),
+ TV_TRANSLATE)
&& tv_list_flatten(list, maxdepth) == OK) {
tv_copy(&argvars[0], rettv);
}
@@ -1915,7 +1915,7 @@ static void f_extend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
list_T *const l1 = argvars[0].vval.v_list;
list_T *const l2 = argvars[1].vval.v_list;
- if (!var_check_lock(tv_list_locked(l1), arg_errmsg, TV_TRANSLATE)) {
+ if (!value_check_lock(tv_list_locked(l1), arg_errmsg, TV_TRANSLATE)) {
listitem_T *item;
if (argvars[2].v_type != VAR_UNKNOWN) {
long before = (long)tv_get_number_chk(&argvars[2], &error);
@@ -1944,13 +1944,13 @@ static void f_extend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
dict_T *const d1 = argvars[0].vval.v_dict;
dict_T *const d2 = argvars[1].vval.v_dict;
if (d1 == NULL) {
- const bool locked = var_check_lock(VAR_FIXED, arg_errmsg, TV_TRANSLATE);
+ const bool locked = value_check_lock(VAR_FIXED, arg_errmsg, TV_TRANSLATE);
(void)locked;
assert(locked == true);
} else if (d2 == NULL) {
// Do nothing
tv_copy(&argvars[0], rettv);
- } else if (!var_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) {
+ } else if (!value_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) {
const char *action = "force";
// Check the third argument.
if (argvars[2].v_type != VAR_UNKNOWN) {
@@ -2022,7 +2022,7 @@ static void f_filewritable(typval_T *argvars, typval_T *rettv, EvalFuncData fptr
static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what)
{
char *fresult = NULL;
- char *path = *curbuf->b_p_path == NUL ? (char *)p_path : curbuf->b_p_path;
+ char *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
int count = 1;
bool first = true;
bool error = false;
@@ -2248,7 +2248,7 @@ static void f_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->v_type = (*what == 'f' ? VAR_FUNC : VAR_STRING);
assert(name != NULL);
if (rettv->v_type == VAR_FUNC) {
- func_ref((char_u *)name);
+ func_ref((char *)name);
}
if (*what == 'n' && pt->pt_name == NULL && pt->pt_func != NULL) {
// use <SNR> instead of the byte code
@@ -2982,8 +2982,8 @@ static void f_globpath(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
const char *const file = tv_get_string_buf_chk(&argvars[1], buf1);
if (file != NULL && !error) {
garray_T ga;
- ga_init(&ga, (int)sizeof(char_u *), 10);
- globpath((char *)tv_get_string(&argvars[0]), (char *)file, &ga, flags);
+ ga_init(&ga, (int)sizeof(char *), 10);
+ globpath((char *)tv_get_string(&argvars[0]), (char *)file, &ga, flags, false);
if (rettv->v_type == VAR_STRING) {
rettv->vval.v_string = ga_concat_strings_sep(&ga, "\n");
@@ -3064,9 +3064,6 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
"conceal",
"cursorbind",
"cursorshape",
-#ifdef DEBUG
- "debug",
-#endif
"dialog_con",
"diff",
"digraphs",
@@ -3082,9 +3079,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
"fork",
#endif
"gettext",
-#if defined(HAVE_ICONV)
"iconv",
-#endif
"insert_expand",
"jumplist",
"keymap",
@@ -3556,8 +3551,8 @@ static void f_insert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
blob_T *const b = argvars[0].vval.v_blob;
if (b == NULL
- || var_check_lock(b->bv_lock, N_("insert() argument"),
- TV_TRANSLATE)) {
+ || value_check_lock(b->bv_lock, N_("insert() argument"),
+ TV_TRANSLATE)) {
return;
}
@@ -3584,16 +3579,16 @@ static void f_insert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
ga_grow(&b->bv_ga, 1);
- char_u *const p = (char_u *)b->bv_ga.ga_data;
+ uint8_t *const p = (uint8_t *)b->bv_ga.ga_data;
memmove(p + before + 1, p + before, (size_t)(len - before));
- *(p + before) = (char_u)val;
+ *(p + before) = (uint8_t)val;
b->bv_ga.ga_len++;
tv_copy(&argvars[0], rettv);
} else if (argvars[0].v_type != VAR_LIST) {
semsg(_(e_listblobarg), "insert()");
- } else if (!var_check_lock(tv_list_locked((l = argvars[0].vval.v_list)),
- N_("insert() argument"), TV_TRANSLATE)) {
+ } else if (!value_check_lock(tv_list_locked((l = argvars[0].vval.v_list)),
+ N_("insert() argument"), TV_TRANSLATE)) {
long before = 0;
if (argvars[2].v_type != VAR_UNKNOWN) {
before = tv_get_number_chk(&argvars[2], &error);
@@ -4488,7 +4483,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv,
}
}
- match = vim_regexec_nl(&regmatch, (char_u *)str, startcol);
+ match = vim_regexec_nl(&regmatch, str, startcol);
if (match && --nth <= 0) {
break;
@@ -5885,7 +5880,7 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
q[-1] = NUL;
q = path_tail(p);
}
- if (q > p && !path_is_absolute((const char_u *)buf)) {
+ if (q > p && !path_is_absolute(buf)) {
// Symlink is relative to directory of argument. Replace the
// symlink with the resolved name in the same directory.
const size_t p_len = strlen(p);
@@ -5976,7 +5971,7 @@ static void f_reverse(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
const int len = tv_blob_len(b);
for (int i = 0; i < len / 2; i++) {
- const char_u tmp = tv_blob_get(b, i);
+ const uint8_t tmp = tv_blob_get(b, i);
tv_blob_set(b, i, tv_blob_get(b, len - i - 1));
tv_blob_set(b, len - i - 1, tmp);
}
@@ -5985,8 +5980,8 @@ static void f_reverse(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
semsg(_(e_listblobarg), "reverse()");
} else {
list_T *const l = argvars[0].vval.v_list;
- if (!var_check_lock(tv_list_locked(l), N_("reverse() argument"),
- TV_TRANSLATE)) {
+ if (!value_check_lock(tv_list_locked(l), N_("reverse() argument"),
+ TV_TRANSLATE)) {
tv_list_reverse(l);
tv_list_set_ret(rettv, l);
}
@@ -6228,7 +6223,7 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
// Repeat until {skip} returns false.
for (;;) {
subpatnum
- = searchit(curwin, curbuf, &pos, NULL, dir, (char_u *)pat, 1, options, RE_SEARCH, &sia);
+ = searchit(curwin, curbuf, &pos, NULL, dir, (char *)pat, 1, options, RE_SEARCH, &sia);
// finding the first match again means there is no match where {skip}
// evaluates to zero.
if (firstpos.lnum != 0 && equalpos(pos, firstpos)) {
@@ -6239,7 +6234,9 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp)
// didn't find it or no skip argument
break;
}
- firstpos = pos;
+ if (firstpos.lnum == 0) {
+ firstpos = pos;
+ }
// If the skip expression matches, ignore this match.
{
@@ -6468,7 +6465,7 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
// Allocate extra memory for the argument vector and the NULL pointer
int argvl = argsl + 2;
- char **argv = xmalloc(sizeof(char_u *) * (size_t)argvl);
+ char **argv = xmalloc(sizeof(char *) * (size_t)argvl);
// Copy program name
argv[0] = xstrdup(argvars[0].vval.v_string);
@@ -6644,7 +6641,7 @@ static void f_searchdecl(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
}
if (!error && name != NULL) {
- rettv->vval.v_number = find_decl((char_u *)name, strlen(name), locally,
+ rettv->vval.v_number = find_decl((char *)name, strlen(name), locally,
thisblock, SEARCH_KEEP) == FAIL;
}
}
@@ -6810,7 +6807,7 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir
.sa_tm = &tm,
};
- int n = searchit(curwin, curbuf, &pos, NULL, dir, (char_u *)pat, 1L,
+ int n = searchit(curwin, curbuf, &pos, NULL, dir, pat, 1L,
options, RE_SEARCH, &sia);
if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos))) {
// didn't find it or found the first match again: FAIL
@@ -7069,11 +7066,11 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, EvalFuncData fpt
return;
}
- char_u *const csearch = (char_u *)tv_dict_get_string(d, "char", false);
+ char *const csearch = tv_dict_get_string(d, "char", false);
if (csearch != NULL) {
int pcc[MAX_MCO];
- const int c = utfc_ptr2char((char *)csearch, pcc);
- set_last_csearch(c, csearch, utfc_ptr2len((char *)csearch));
+ const int c = utfc_ptr2char(csearch, pcc);
+ set_last_csearch(c, csearch, utfc_ptr2len(csearch));
}
dictitem_T *di = tv_dict_find(d, S_LEN("forward"));
@@ -7553,7 +7550,7 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, EvalFuncData fptr
if (str != NULL) {
// Check the argument for spelling.
while (*str != NUL) {
- len = spell_check(curwin, (char_u *)str, &attr, &capcol, false);
+ len = spell_check(curwin, (char *)str, &attr, &capcol, false);
if (attr != HLF_COUNT) {
word = str;
break;
@@ -7612,7 +7609,7 @@ static void f_spellsuggest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr
maxcount = 25;
}
- spell_suggest_list(&ga, (char_u *)str, maxcount, need_capital, false);
+ spell_suggest_list(&ga, (char *)str, maxcount, need_capital, false);
f_spellsuggest_return:
tv_list_alloc_ret(rettv, (ptrdiff_t)ga.ga_len);
@@ -7668,7 +7665,7 @@ static void f_split(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (*str == NUL) {
match = false; // Empty item at the end.
} else {
- match = vim_regexec_nl(&regmatch, (char_u *)str, col);
+ match = vim_regexec_nl(&regmatch, (char *)str, col);
}
const char *end;
if (match) {
@@ -7823,34 +7820,35 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
// MSVC returns NULL for an invalid value of seconds.
if (curtime_ptr == NULL) {
rettv->vval.v_string = xstrdup(_("(Invalid)"));
- } else {
- vimconv_T conv;
+ return;
+ }
- conv.vc_type = CONV_NONE;
- char *enc = (char *)enc_locale();
- convert_setup(&conv, p_enc, enc);
- if (conv.vc_type != CONV_NONE) {
- p = string_convert(&conv, p, NULL);
- }
- char result_buf[256];
- if (p == NULL || strftime(result_buf, sizeof(result_buf), p, curtime_ptr) == 0) {
- result_buf[0] = NUL;
- }
+ vimconv_T conv;
- if (conv.vc_type != CONV_NONE) {
- xfree(p);
- }
- convert_setup(&conv, enc, p_enc);
- if (conv.vc_type != CONV_NONE) {
- rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
- } else {
- rettv->vval.v_string = xstrdup(result_buf);
- }
+ conv.vc_type = CONV_NONE;
+ char *enc = enc_locale();
+ convert_setup(&conv, p_enc, enc);
+ if (conv.vc_type != CONV_NONE) {
+ p = string_convert(&conv, p, NULL);
+ }
+ char result_buf[256];
+ if (p == NULL || strftime(result_buf, sizeof(result_buf), p, curtime_ptr) == 0) {
+ result_buf[0] = NUL;
+ }
- // Release conversion descriptors.
- convert_setup(&conv, NULL, NULL);
- xfree(enc);
+ if (conv.vc_type != CONV_NONE) {
+ xfree(p);
}
+ convert_setup(&conv, enc, p_enc);
+ if (conv.vc_type != CONV_NONE) {
+ rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
+ } else {
+ rettv->vval.v_string = xstrdup(result_buf);
+ }
+
+ // Release conversion descriptors.
+ convert_setup(&conv, NULL, NULL);
+ xfree(enc);
}
/// "strgetchar()" function
@@ -7930,11 +7928,11 @@ static void strchar_common(typval_T *argvars, typval_T *rettv, bool skipcc)
{
const char *s = tv_get_string(&argvars[0]);
varnumber_T len = 0;
- int (*func_mb_ptr2char_adv)(const char_u **pp);
+ int (*func_mb_ptr2char_adv)(const char **pp);
func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv;
while (*s != NUL) {
- func_mb_ptr2char_adv((const char_u **)&s);
+ func_mb_ptr2char_adv(&s);
len++;
}
rettv->vval.v_number = len;
@@ -8097,7 +8095,7 @@ static void f_strptime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
vimconv_T conv = {
.vc_type = CONV_NONE,
};
- char *enc = (char *)enc_locale();
+ char *enc = enc_locale();
convert_setup(&conv, p_enc, enc);
if (conv.vc_type != CONV_NONE) {
fmt = string_convert(&conv, fmt, NULL);
@@ -8654,6 +8652,7 @@ static void f_timer_pause(typval_T *argvars, typval_T *unused, EvalFuncData fptr
emsg(_(e_number_exp));
return;
}
+
int paused = (bool)tv_get_number(&argvars[1]);
timer_T *timer = find_timer_by_nr(tv_get_number(&argvars[0]));
if (timer != NULL) {
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index 7c61a2f990..c298064d86 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -900,8 +900,8 @@ void tv_list_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg)
list_T *l;
bool error = false;
- if (var_check_lock(tv_list_locked((l = argvars[0].vval.v_list)),
- arg_errmsg, TV_TRANSLATE)) {
+ if (value_check_lock(tv_list_locked((l = argvars[0].vval.v_list)),
+ arg_errmsg, TV_TRANSLATE)) {
return;
}
@@ -1156,7 +1156,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
semsg(_(e_listarg), sort ? "sort()" : "uniq()");
} else {
list_T *const l = argvars[0].vval.v_list;
- if (var_check_lock(tv_list_locked(l), arg_errmsg, TV_TRANSLATE)) {
+ if (value_check_lock(tv_list_locked(l), arg_errmsg, TV_TRANSLATE)) {
goto theend;
}
tv_list_set_ret(rettv, l);
@@ -1599,7 +1599,7 @@ void callback_free(Callback *callback)
{
switch (callback->type) {
case kCallbackFuncref:
- func_unref((char_u *)callback->data.funcref);
+ func_unref(callback->data.funcref);
xfree(callback->data.funcref);
break;
case kCallbackPartial:
@@ -1628,7 +1628,7 @@ void callback_put(Callback *cb, typval_T *tv)
case kCallbackFuncref:
tv->v_type = VAR_FUNC;
tv->vval.v_string = xstrdup(cb->data.funcref);
- func_ref((char_u *)cb->data.funcref);
+ func_ref(cb->data.funcref);
break;
case kCallbackLua:
// TODO(tjdevries): Unified Callback.
@@ -1654,7 +1654,7 @@ void callback_copy(Callback *dest, Callback *src)
break;
case kCallbackFuncref:
dest->data.funcref = xstrdup(src->data.funcref);
- func_ref((char_u *)src->data.funcref);
+ func_ref(src->data.funcref);
break;
case kCallbackLua:
dest->data.luaref = api_new_luaref(src->data.luaref);
@@ -2494,7 +2494,7 @@ void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action
} else if (*action == 'f' && di2 != di1) {
typval_T oldtv;
- if (var_check_lock(di1->di_tv.v_lock, arg_errmsg, arg_errmsg_len)
+ if (value_check_lock(di1->di_tv.v_lock, arg_errmsg, arg_errmsg_len)
|| var_check_ro(di1->di_flags, arg_errmsg, arg_errmsg_len)) {
break;
}
@@ -2710,7 +2710,7 @@ void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg)
{
blob_T *const b = argvars[0].vval.v_blob;
- if (b != NULL && var_check_lock(b->bv_lock, arg_errmsg, TV_TRANSLATE)) {
+ if (b != NULL && value_check_lock(b->bv_lock, arg_errmsg, TV_TRANSLATE)) {
return;
}
@@ -2730,7 +2730,7 @@ void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg)
}
if (argvars[2].v_type == VAR_UNKNOWN) {
// Remove one item, return its value.
- char_u *const p = (char_u *)b->bv_ga.ga_data;
+ uint8_t *const p = (uint8_t *)b->bv_ga.ga_data;
rettv->vval.v_number = (varnumber_T)(*(p + idx));
memmove(p + idx, p + idx + 1, (size_t)(len - idx - 1));
b->bv_ga.ga_len--;
@@ -2752,9 +2752,8 @@ void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg)
blob->bv_ga.ga_len = (int)(end - idx + 1);
ga_grow(&blob->bv_ga, (int)(end - idx + 1));
- char_u *const p = (char_u *)b->bv_ga.ga_data;
- memmove((char_u *)blob->bv_ga.ga_data, p + idx,
- (size_t)(end - idx + 1));
+ uint8_t *const p = (uint8_t *)b->bv_ga.ga_data;
+ memmove(blob->bv_ga.ga_data, p + idx, (size_t)(end - idx + 1));
tv_blob_set_ret(rettv, blob);
if (len - end - 1 > 0) {
@@ -2902,7 +2901,7 @@ void tv_dict_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg)
if (argvars[2].v_type != VAR_UNKNOWN) {
semsg(_(e_toomanyarg), "remove()");
} else if ((d = argvars[0].vval.v_dict) != NULL
- && !var_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE)) {
+ && !value_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE)) {
const char *key = tv_get_string_chk(&argvars[1]);
if (key != NULL) {
dictitem_T *di = tv_dict_find(d, key, -1);
@@ -3007,7 +3006,7 @@ void tv_blob_copy(typval_T *const from, typval_T *const to)
(tv)->v_lock = VAR_UNLOCKED; \
} while (0)
-static inline int _nothing_conv_func_start(typval_T *const tv, char_u *const fun)
+static inline int _nothing_conv_func_start(typval_T *const tv, char *const fun)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ARG(1)
{
tv->v_lock = VAR_UNLOCKED;
@@ -3209,17 +3208,19 @@ static inline void _nothing_conv_dict_end(typval_T *const tv, dict_T **const dic
/// @param[in,out] tv Value to free.
void tv_clear(typval_T *const tv)
{
- if (tv != NULL && tv->v_type != VAR_UNKNOWN) {
- // WARNING: do not translate the string here, gettext is slow and function
- // is used *very* often. At the current state encode_vim_to_nothing() does
- // not error out and does not use the argument anywhere.
- //
- // If situation changes and this argument will be used, translate it in the
- // place where it is used.
- const int evn_ret = encode_vim_to_nothing(NULL, tv, "tv_clear() argument");
- (void)evn_ret;
- assert(evn_ret == OK);
+ if (tv == NULL || tv->v_type == VAR_UNKNOWN) {
+ return;
}
+
+ // WARNING: do not translate the string here, gettext is slow and function
+ // is used *very* often. At the current state encode_vim_to_nothing() does
+ // not error out and does not use the argument anywhere.
+ //
+ // If situation changes and this argument will be used, translate it in the
+ // place where it is used.
+ const int evn_ret = encode_vim_to_nothing(NULL, tv, "tv_clear() argument");
+ (void)evn_ret;
+ assert(evn_ret == OK);
}
//{{{3 Free
@@ -3229,35 +3230,37 @@ void tv_clear(typval_T *const tv)
/// @param tv Object to free.
void tv_free(typval_T *tv)
{
- if (tv != NULL) {
- switch (tv->v_type) {
- case VAR_PARTIAL:
- partial_unref(tv->vval.v_partial);
- break;
- case VAR_FUNC:
- func_unref((char_u *)tv->vval.v_string);
- FALLTHROUGH;
- case VAR_STRING:
- xfree(tv->vval.v_string);
- break;
- case VAR_BLOB:
- tv_blob_unref(tv->vval.v_blob);
- break;
- case VAR_LIST:
- tv_list_unref(tv->vval.v_list);
- break;
- case VAR_DICT:
- tv_dict_unref(tv->vval.v_dict);
- break;
- case VAR_BOOL:
- case VAR_SPECIAL:
- case VAR_NUMBER:
- case VAR_FLOAT:
- case VAR_UNKNOWN:
- break;
- }
- xfree(tv);
+ if (tv == NULL) {
+ return;
+ }
+
+ switch (tv->v_type) {
+ case VAR_PARTIAL:
+ partial_unref(tv->vval.v_partial);
+ break;
+ case VAR_FUNC:
+ func_unref(tv->vval.v_string);
+ FALLTHROUGH;
+ case VAR_STRING:
+ xfree(tv->vval.v_string);
+ break;
+ case VAR_BLOB:
+ tv_blob_unref(tv->vval.v_blob);
+ break;
+ case VAR_LIST:
+ tv_list_unref(tv->vval.v_list);
+ break;
+ case VAR_DICT:
+ tv_dict_unref(tv->vval.v_dict);
+ break;
+ case VAR_BOOL:
+ case VAR_SPECIAL:
+ case VAR_NUMBER:
+ case VAR_FLOAT:
+ case VAR_UNKNOWN:
+ break;
}
+ xfree(tv);
}
//{{{3 Copy
@@ -3288,7 +3291,7 @@ void tv_copy(const typval_T *const from, typval_T *const to)
if (from->vval.v_string != NULL) {
to->vval.v_string = xstrdup(from->vval.v_string);
if (from->v_type == VAR_FUNC) {
- func_ref((char_u *)to->vval.v_string);
+ func_ref(to->vval.v_string);
}
}
break;
@@ -3460,12 +3463,12 @@ bool tv_check_lock(const typval_T *tv, const char *name, size_t name_len)
default:
break;
}
- return var_check_lock(tv->v_lock, name, name_len)
- || (lock != VAR_UNLOCKED && var_check_lock(lock, name, name_len));
+ return value_check_lock(tv->v_lock, name, name_len)
+ || (lock != VAR_UNLOCKED && value_check_lock(lock, name, name_len));
}
-/// @return true if variable "name" is locked (immutable)
-bool var_check_lock(VarLockStatus lock, const char *name, size_t name_len)
+/// @return true if variable "name" has a locked (immutable) value
+bool value_check_lock(VarLockStatus lock, const char *name, size_t name_len)
{
const char *error_message = NULL;
switch (lock) {
diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h
index 1ee3b5bf69..3f59cd3547 100644
--- a/src/nvim/eval/typval.h
+++ b/src/nvim/eval/typval.h
@@ -358,7 +358,7 @@ static inline int tv_blob_len(const blob_T *const b)
return b->bv_ga.ga_len;
}
-static inline char_u tv_blob_get(const blob_T *b, int idx)
+static inline uint8_t tv_blob_get(const blob_T *b, int idx)
REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT;
/// Get the byte at index `idx` in the blob.
@@ -367,12 +367,12 @@ static inline char_u tv_blob_get(const blob_T *b, int idx)
/// @param[in] idx Index in a blob. Must be valid.
///
/// @return Byte value at the given index.
-static inline char_u tv_blob_get(const blob_T *const b, int idx)
+static inline uint8_t tv_blob_get(const blob_T *const b, int idx)
{
- return ((char_u *)b->bv_ga.ga_data)[idx];
+ return ((uint8_t *)b->bv_ga.ga_data)[idx];
}
-static inline void tv_blob_set(blob_T *b, int idx, char_u c)
+static inline void tv_blob_set(blob_T *b, int idx, uint8_t c)
REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL;
/// Store the byte `c` at index `idx` in the blob.
@@ -380,9 +380,9 @@ static inline void tv_blob_set(blob_T *b, int idx, char_u c)
/// @param[in] b Blob to index. Cannot be NULL.
/// @param[in] idx Index in a blob. Must be valid.
/// @param[in] c Value to store.
-static inline void tv_blob_set(blob_T *const b, int idx, char_u c)
+static inline void tv_blob_set(blob_T *const b, int idx, uint8_t c)
{
- ((char_u *)b->bv_ga.ga_data)[idx] = c;
+ ((uint8_t *)b->bv_ga.ga_data)[idx] = c;
}
/// Initialize VimL object
diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h
index 939e5d0810..4615198441 100644
--- a/src/nvim/eval/typval_defs.h
+++ b/src/nvim/eval/typval_defs.h
@@ -337,7 +337,7 @@ struct ufunc {
///< used for s: variables
int uf_refcount; ///< reference count, see func_name_refcount()
funccall_T *uf_scoped; ///< l: local variables for closure
- char_u *uf_name_exp; ///< if "uf_name[]" starts with SNR the name with
+ char *uf_name_exp; ///< if "uf_name[]" starts with SNR the name with
///< "<SNR>" as a string, otherwise NULL
char uf_name[]; ///< Name of function (actual size equals name);
///< can start with <SNR>123_
diff --git a/src/nvim/eval/typval_encode.c.h b/src/nvim/eval/typval_encode.c.h
index 6c931d3f88..6d29286a58 100644
--- a/src/nvim/eval/typval_encode.c.h
+++ b/src/nvim/eval/typval_encode.c.h
@@ -339,7 +339,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
tv_blob_len(tv->vval.v_blob));
break;
case VAR_FUNC:
- TYPVAL_ENCODE_CONV_FUNC_START(tv, (char_u *)tv->vval.v_string);
+ TYPVAL_ENCODE_CONV_FUNC_START(tv, tv->vval.v_string);
TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, 0);
TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, -1);
TYPVAL_ENCODE_CONV_FUNC_END(tv);
@@ -347,7 +347,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE(
case VAR_PARTIAL: {
partial_T *const pt = tv->vval.v_partial;
(void)pt;
- TYPVAL_ENCODE_CONV_FUNC_START(tv, (pt == NULL ? NULL : (char_u *)partial_name(pt))); // -V547
+ TYPVAL_ENCODE_CONV_FUNC_START(tv, (pt == NULL ? NULL : partial_name(pt))); // -V547
_mp_push(*mpstack, ((MPConvStackVal) { // -V779
.type = kMPConvPartial,
.tv = tv,
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index c70d56cd25..6c6dc3fa43 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -45,6 +45,7 @@
#include "nvim/runtime.h"
#include "nvim/search.h"
#include "nvim/strings.h"
+#include "nvim/types.h"
#include "nvim/ui.h"
#include "nvim/vim.h"
@@ -83,7 +84,7 @@ hashtab_T *func_tbl_get(void)
}
/// Get function arguments.
-static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int *varargs,
+static int get_function_args(char **argp, char endchar, garray_T *newargs, int *varargs,
garray_T *default_args, bool skip)
{
bool mustend = false;
@@ -105,7 +106,7 @@ static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int
// Isolate the arguments: "arg1, arg2, ...)"
bool any_default = false;
- while (*p != (char)endchar) {
+ while (*p != endchar) {
if (p[0] == '.' && p[1] == '.' && p[2] == '.') {
if (varargs != NULL) {
*varargs = true;
@@ -117,7 +118,7 @@ static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int
while (ASCII_ISALNUM(*p) || *p == '_') {
p++;
}
- if (arg == p || isdigit(*arg)
+ if (arg == p || isdigit((uint8_t)(*arg))
|| (p - arg == 9 && strncmp(arg, "firstline", 9) == 0)
|| (p - arg == 8 && strncmp(arg, "lastline", 8) == 0)) {
if (!skip) {
@@ -187,14 +188,14 @@ static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int
}
}
p = skipwhite(p);
- if (mustend && *p != (char)endchar) {
+ if (mustend && *p != endchar) {
if (!skip) {
semsg(_(e_invarg2), *argp);
}
break;
}
}
- if (*p != (char)endchar) {
+ if (*p != endchar) {
goto err_ret;
}
p++; // skip "endchar"
@@ -228,12 +229,12 @@ static void register_closure(ufunc_T *fp)
}
/// @return a name for a lambda. Returned in static memory.
-char_u *get_lambda_name(void)
+char *get_lambda_name(void)
{
- static char_u name[30];
+ static char name[30];
static int lambda_no = 0;
- snprintf((char *)name, sizeof(name), "<lambda>%d", ++lambda_no);
+ snprintf(name, sizeof(name), "<lambda>%d", ++lambda_no);
return name;
}
@@ -307,7 +308,7 @@ int get_lambda_tv(char **arg, typval_T *rettv, bool evaluate)
char *p;
garray_T newlines;
- char *name = (char *)get_lambda_name();
+ char *name = get_lambda_name();
fp = xcalloc(1, offsetof(ufunc_T, uf_name) + strlen(name) + 1);
pt = xcalloc(1, sizeof(partial_T));
@@ -581,9 +582,9 @@ static char *fname_trans_sid(const char *const name, char *const fname_buf, char
/// Find a function by name, return pointer to it in ufuncs.
///
/// @return NULL for unknown function.
-ufunc_T *find_func(const char_u *name)
+ufunc_T *find_func(const char *name)
{
- hashitem_T *hi = hash_find(&func_hashtab, (char *)name);
+ hashitem_T *hi = hash_find(&func_hashtab, name);
if (!HASHITEM_EMPTY(hi)) {
return HI2UF(hi);
}
@@ -759,13 +760,12 @@ static void funccal_unref(funccall_T *fc, ufunc_T *fp, bool force)
static bool func_remove(ufunc_T *fp)
{
hashitem_T *hi = hash_find(&func_hashtab, (char *)UF2HIKEY(fp));
-
- if (!HASHITEM_EMPTY(hi)) {
- hash_remove(&func_hashtab, hi);
- return true;
+ if (HASHITEM_EMPTY(hi)) {
+ return false;
}
- return false;
+ hash_remove(&func_hashtab, hi);
+ return true;
}
static void func_clear_items(ufunc_T *fp)
@@ -1225,9 +1225,9 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
/// For the first we only count the name stored in func_hashtab as a reference,
/// using function() does not count as a reference, because the function is
/// looked up by name.
-static bool func_name_refcount(const char_u *name)
+static bool func_name_refcount(const char *name)
{
- return isdigit(*name) || *name == '<';
+ return isdigit((uint8_t)(*name)) || *name == '<';
}
/// Call a user function after checking the arguments.
@@ -1318,7 +1318,7 @@ void free_all_functions(void)
// Only free functions that are not refcounted, those are
// supposed to be freed when no longer referenced.
fp = HI2UF(hi);
- if (func_name_refcount((char_u *)fp->uf_name)) {
+ if (func_name_refcount(fp->uf_name)) {
skipped++;
} else {
changed = func_hashtab.ht_changed;
@@ -1344,7 +1344,7 @@ void free_all_functions(void)
// Only free functions that are not refcounted, those are
// supposed to be freed when no longer referenced.
fp = HI2UF(hi);
- if (func_name_refcount((char_u *)fp->uf_name)) {
+ if (func_name_refcount(fp->uf_name)) {
skipped++;
} else {
func_free(fp);
@@ -1381,7 +1381,7 @@ static bool builtin_function(const char *name, int len)
return p == NULL;
}
-int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict, typval_T *rettv)
+int func_call(char *name, typval_T *args, partial_T *partial, dict_T *selfdict, typval_T *rettv)
{
typval_T argv[MAX_FUNC_ARGS + 1];
int argc = 0;
@@ -1403,7 +1403,7 @@ int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict
funcexe.fe_evaluate = true;
funcexe.fe_partial = partial;
funcexe.fe_selfdict = selfdict;
- r = call_func((char *)name, -1, rettv, argc, argv, &funcexe);
+ r = call_func(name, -1, rettv, argc, argv, &funcexe);
func_call_skip_call:
// Free the arguments.
@@ -1434,30 +1434,30 @@ varnumber_T callback_call_retnr(Callback *callback, int argcount, typval_T *argv
/// Give an error message for the result of a function.
/// Nothing if "error" is FCERR_NONE.
-static void user_func_error(int error, const char_u *name)
+static void user_func_error(int error, const char *name)
FUNC_ATTR_NONNULL_ALL
{
switch (error) {
case FCERR_UNKNOWN:
- emsg_funcname(N_("E117: Unknown function: %s"), (char *)name);
+ emsg_funcname(N_("E117: Unknown function: %s"), name);
break;
case FCERR_NOTMETHOD:
- emsg_funcname(N_("E276: Cannot use function as a method: %s"), (char *)name);
+ emsg_funcname(N_("E276: Cannot use function as a method: %s"), name);
break;
case FCERR_DELETED:
- emsg_funcname(N_("E933: Function was deleted: %s"), (char *)name);
+ emsg_funcname(N_("E933: Function was deleted: %s"), name);
break;
case FCERR_TOOMANY:
- emsg_funcname(_(e_toomanyarg), (char *)name);
+ emsg_funcname(_(e_toomanyarg), name);
break;
case FCERR_TOOFEW:
- emsg_funcname(N_("E119: Not enough arguments for function: %s"), (char *)name);
+ emsg_funcname(N_("E119: Not enough arguments for function: %s"), name);
break;
case FCERR_SCRIPT:
- emsg_funcname(N_("E120: Using <SID> not in a script context: %s"), (char *)name);
+ emsg_funcname(N_("E120: Using <SID> not in a script context: %s"), name);
break;
case FCERR_DICT:
- emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"), (char *)name);
+ emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"), name);
break;
}
}
@@ -1579,7 +1579,7 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
} else if (fp != NULL || !builtin_function((const char *)rfname, -1)) {
// User defined function.
if (fp == NULL) {
- fp = find_func((char_u *)rfname);
+ fp = find_func(rfname);
}
// Trigger FuncUndefined event, may load the function.
@@ -1587,13 +1587,13 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
&& apply_autocmds(EVENT_FUNCUNDEFINED, rfname, rfname, true, NULL)
&& !aborting()) {
// executed an autocommand, search for the function again
- fp = find_func((char_u *)rfname);
+ fp = find_func(rfname);
}
// Try loading a package.
if (fp == NULL && script_autoload((const char *)rfname, strlen(rfname),
true) && !aborting()) {
// Loaded a package, search for the function again.
- fp = find_func((char_u *)rfname);
+ fp = find_func(rfname);
}
if (fp != NULL && (fp->uf_flags & FC_DELETED)) {
@@ -1611,7 +1611,7 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
} else if (funcexe->fe_basetv != NULL) {
// expr->method(): Find the method name in the table, call its
// implementation with the base as one of the arguments.
- error = call_internal_method((char_u *)fname, argcount, argvars, rettv,
+ error = call_internal_method(fname, argcount, argvars, rettv,
funcexe->fe_basetv);
} else {
// Find the function name in the table, call its implementation.
@@ -1635,7 +1635,7 @@ theend:
// Report an error unless the argument evaluation or function call has been
// cancelled due to an aborting error, an interrupt, or an exception.
if (!aborting()) {
- user_func_error(error, (name != NULL) ? (char_u *)name : (char_u *)funcname);
+ user_func_error(error, (name != NULL) ? name : funcname);
}
// clear the copies made from the partial
@@ -1651,7 +1651,7 @@ theend:
char *printable_func_name(ufunc_T *fp)
{
- return fp->uf_name_exp != NULL ? (char *)fp->uf_name_exp : fp->uf_name;
+ return fp->uf_name_exp != NULL ? fp->uf_name_exp : fp->uf_name;
}
/// List the head of the function: "name(arg1, arg2)".
@@ -1723,7 +1723,7 @@ static void list_func_head(ufunc_T *fp, int indent, bool force)
/// @param partial return: partial of a FuncRef
///
/// @return the function name in allocated memory, or NULL for failure.
-char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, partial_T **partial)
+char *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, partial_T **partial)
FUNC_ATTR_NONNULL_ARG(1)
{
char *name = NULL;
@@ -1744,7 +1744,7 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa
&& (*pp)[2] == KE_SNR) {
*pp += 3;
len = get_id_len((const char **)pp) + 3;
- return (char_u *)xmemdupz(start, (size_t)len);
+ return xmemdupz(start, (size_t)len);
}
// A name starting with "<SID>" or "<SNR>" is local to a script. But
@@ -1923,7 +1923,7 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa
theend:
clear_lval(&lv);
- return (char_u *)name;
+ return name;
}
/// If the "funcname" starts with "s:" or "<SID>", then expands it to the
@@ -1975,7 +1975,7 @@ char *save_function_name(char **name, bool skip, int flags, funcdict_T *fudi)
CLEAR_POINTER(fudi);
}
} else {
- saved = (char *)trans_function_name(&p, skip, flags, fudi, NULL);
+ saved = trans_function_name(&p, skip, flags, fudi, NULL);
}
*name = p;
return saved;
@@ -2000,8 +2000,8 @@ static void list_functions(regmatch_T *regmatch)
if ((fp->uf_flags & FC_DEAD) == 0
&& (regmatch == NULL
? (!message_filtered((char *)fp->uf_name)
- && !func_name_refcount((char_u *)fp->uf_name))
- : (!isdigit(*fp->uf_name)
+ && !func_name_refcount(fp->uf_name))
+ : (!isdigit((uint8_t)(*fp->uf_name))
&& vim_regexec(regmatch, (char *)fp->uf_name, 0)))) {
list_func_head(fp, false, false);
if (changed != func_hashtab.ht_changed) {
@@ -2132,7 +2132,7 @@ void ex_function(exarg_T *eap)
*p = NUL;
}
if (!eap->skip && !got_int) {
- fp = find_func((char_u *)name);
+ fp = find_func(name);
if (fp != NULL) {
list_func_head(fp, !eap->forceit, eap->forceit);
for (int j = 0; j < fp->uf_lines.ga_len && !got_int; j++) {
@@ -2255,7 +2255,7 @@ void ex_function(exarg_T *eap)
if (!eap->skip && !eap->forceit) {
if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL) {
emsg(_(e_funcdict));
- } else if (name != NULL && find_func((char_u *)name) != NULL) {
+ } else if (name != NULL && find_func(name) != NULL) {
emsg_funcname(e_funcexts, name);
}
}
@@ -2295,7 +2295,7 @@ void ex_function(exarg_T *eap)
} else {
xfree(line_to_free);
if (eap->getline == NULL) {
- theline = (char *)getcmdline(':', 0L, indent, do_concat);
+ theline = getcmdline(':', 0L, indent, do_concat);
} else {
theline = eap->getline(':', eap->cookie, indent, do_concat);
}
@@ -2509,7 +2509,7 @@ void ex_function(exarg_T *eap)
goto erret;
}
- fp = find_func((char_u *)name);
+ fp = find_func(name);
if (fp != NULL) {
// Function can be replaced with "function!" and when sourcing the
// same script again, but only once.
@@ -2531,7 +2531,7 @@ void ex_function(exarg_T *eap)
fp = NULL;
overwrite = true;
} else {
- char_u *exp_name = fp->uf_name_exp;
+ char *exp_name = fp->uf_name_exp;
// redefine existing function, keep the expanded name
XFREE_CLEAR(name);
fp->uf_name_exp = NULL;
@@ -2550,13 +2550,13 @@ void ex_function(exarg_T *eap)
goto erret;
}
if (fudi.fd_di == NULL) {
- if (var_check_lock(fudi.fd_dict->dv_lock, (const char *)eap->arg,
- TV_CSTRING)) {
+ if (value_check_lock(fudi.fd_dict->dv_lock, (const char *)eap->arg,
+ TV_CSTRING)) {
// Can't add a function to a locked dictionary
goto erret;
}
- } else if (var_check_lock(fudi.fd_di->di_tv.v_lock, (const char *)eap->arg,
- TV_CSTRING)) {
+ } else if (value_check_lock(fudi.fd_di->di_tv.v_lock, (const char *)eap->arg,
+ TV_CSTRING)) {
// Can't change an existing function if it is locked
goto erret;
}
@@ -2689,7 +2689,7 @@ bool translated_function_exists(const char *name)
if (builtin_function(name, -1)) {
return find_internal_func((char *)name) != NULL;
}
- return find_func((const char_u *)name) != NULL;
+ return find_func(name) != NULL;
}
/// Check whether function with the given name exists
@@ -2707,7 +2707,7 @@ bool function_exists(const char *const name, bool no_deref)
if (no_deref) {
flag |= TFN_NO_DEREF;
}
- char *const p = (char *)trans_function_name((char **)&nm, false, flag, NULL, NULL);
+ char *const p = trans_function_name((char **)&nm, false, flag, NULL, NULL);
nm = skipwhite(nm);
// Only accept "funcname", "funcname ", "funcname (..." and
@@ -2769,7 +2769,7 @@ void ex_delfunction(exarg_T *eap)
{
ufunc_T *fp = NULL;
char *p;
- char_u *name;
+ char *name;
funcdict_T fudi;
p = eap->arg;
@@ -2791,7 +2791,7 @@ void ex_delfunction(exarg_T *eap)
*p = NUL;
}
- if (isdigit(*name) && fudi.fd_dict == NULL) {
+ if (isdigit((uint8_t)(*name)) && fudi.fd_dict == NULL) {
if (!eap->skip) {
semsg(_(e_invarg2), eap->arg);
}
@@ -2832,7 +2832,7 @@ void ex_delfunction(exarg_T *eap)
// it and the refcount is more than one, it should be kept.
// A numbered function or lambda should be kept if the refcount is
// one or more.
- if (fp->uf_refcount > (func_name_refcount((char_u *)fp->uf_name) ? 0 : 1)) {
+ if (fp->uf_refcount > (func_name_refcount(fp->uf_name) ? 0 : 1)) {
// Function is still referenced somewhere. Don't free it but
// do remove it from the hashtable.
if (func_remove(fp)) {
@@ -2848,7 +2848,7 @@ void ex_delfunction(exarg_T *eap)
/// Unreference a Function: decrement the reference count and free it when it
/// becomes zero.
-void func_unref(char_u *name)
+void func_unref(char *name)
{
ufunc_T *fp = NULL;
@@ -2857,7 +2857,7 @@ void func_unref(char_u *name)
}
fp = find_func(name);
- if (fp == NULL && isdigit(*name)) {
+ if (fp == NULL && isdigit((uint8_t)(*name))) {
#ifdef EXITFREE
if (!entered_free_all_mem) {
internal_error("func_unref()");
@@ -2890,7 +2890,7 @@ void func_ptr_unref(ufunc_T *fp)
}
/// Count a reference to a Function.
-void func_ref(char_u *name)
+void func_ref(char *name)
{
ufunc_T *fp;
@@ -2900,7 +2900,7 @@ void func_ref(char_u *name)
fp = find_func(name);
if (fp != NULL) {
(fp->uf_refcount)++;
- } else if (isdigit(*name)) {
+ } else if (isdigit((uint8_t)(*name))) {
// Only give an error for a numbered function.
// Fail silently, when named or lambda function isn't found.
internal_error("func_ref()");
@@ -3017,7 +3017,7 @@ void ex_call(exarg_T *eap)
return;
}
- tofree = (char *)trans_function_name(&arg, false, TFN_INT, &fudi, &partial);
+ tofree = trans_function_name(&arg, false, TFN_INT, &fudi, &partial);
if (fudi.fd_newkey != NULL) {
// Still need to give an error message for missing key.
semsg(_(e_dictkey), fudi.fd_newkey);
@@ -3304,7 +3304,7 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv)
: rettv->vval.v_partial->pt_name;
// Translate "s:func" to the stored function name.
fname = fname_trans_sid(fname, fname_buf, &tofree, &error);
- fp = find_func((char_u *)fname);
+ fp = find_func(fname);
xfree(tofree);
}
@@ -3327,7 +3327,7 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv)
// be referenced elsewhere.
if (ret_pt->pt_name != NULL) {
pt->pt_name = xstrdup(ret_pt->pt_name);
- func_ref((char_u *)pt->pt_name);
+ func_ref(pt->pt_name);
} else {
pt->pt_func = ret_pt->pt_func;
func_ptr_ref(pt->pt_func);
@@ -3348,9 +3348,9 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv)
}
/// @return the name of the executed function.
-char_u *func_name(void *cookie)
+char *func_name(void *cookie)
{
- return (char_u *)((funccall_T *)cookie)->func->uf_name;
+ return ((funccall_T *)cookie)->func->uf_name;
}
/// @return the address holding the next breakpoint line for a funccall cookie.
@@ -3609,7 +3609,7 @@ bool set_ref_in_functions(int copyID)
if (!HASHITEM_EMPTY(hi)) {
todo--;
fp = HI2UF(hi);
- if (!func_name_refcount((char_u *)fp->uf_name)
+ if (!func_name_refcount(fp->uf_name)
&& set_ref_in_func(NULL, fp, copyID)) {
return true;
}
@@ -3635,7 +3635,7 @@ bool set_ref_in_func_args(int copyID)
/// "ht_stack" is used to add hashtabs to be marked. Can be NULL.
///
/// @return true if setting references failed somehow.
-bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID)
+bool set_ref_in_func(char *name, ufunc_T *fp_in, int copyID)
{
ufunc_T *fp = fp_in;
funccall_T *fc;
@@ -3649,8 +3649,8 @@ bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID)
}
if (fp_in == NULL) {
- fname = fname_trans_sid((char *)name, fname_buf, &tofree, &error);
- fp = find_func((char_u *)fname);
+ fname = fname_trans_sid(name, fname_buf, &tofree, &error);
+ fp = find_func(fname);
}
if (fp != NULL) {
for (fc = fp->uf_scoped; fc != NULL; fc = fc->func->uf_scoped) {
@@ -3662,9 +3662,9 @@ bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID)
}
/// Registers a luaref as a lambda.
-char_u *register_luafunc(LuaRef ref)
+char *register_luafunc(LuaRef ref)
{
- char *name = (char *)get_lambda_name();
+ char *name = get_lambda_name();
ufunc_T *fp = xcalloc(1, offsetof(ufunc_T, uf_name) + strlen(name) + 1);
fp->uf_refcount = 1;
@@ -3678,5 +3678,5 @@ char_u *register_luafunc(LuaRef ref)
hash_add(&func_hashtab, UF2HIKEY(fp));
// coverity[leaked_storage]
- return (char_u *)fp->uf_name;
+ return fp->uf_name;
}
diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c
index 206df03381..9ed245d6c4 100644
--- a/src/nvim/eval/vars.c
+++ b/src/nvim/eval/vars.c
@@ -106,7 +106,7 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd)
return NULL;
}
*p = NUL;
- if (islower(*marker)) {
+ if (islower((uint8_t)(*marker))) {
emsg(_("E221: Marker cannot start with lower case letter"));
return NULL;
}
@@ -208,7 +208,7 @@ static void ex_let_const(exarg_T *eap, const bool is_const)
argend--;
}
expr = skipwhite(argend);
- if (*expr != '=' && !((vim_strchr("+-*/%.", *expr) != NULL
+ if (*expr != '=' && !((vim_strchr("+-*/%.", (uint8_t)(*expr)) != NULL
&& expr[1] == '=') || strncmp(expr, "..=", 3) == 0)) {
// ":let" without "=": list variables
if (*arg == '[') {
@@ -244,7 +244,7 @@ static void ex_let_const(exarg_T *eap, const bool is_const)
op[0] = '=';
op[1] = NUL;
if (*expr != '=') {
- if (vim_strchr("+-*/%.", *expr) != NULL) {
+ if (vim_strchr("+-*/%.", (uint8_t)(*expr)) != NULL) {
op[0] = *expr; // +=, -=, *=, /=, %= or .=
if (expr[0] == '.' && expr[1] == '.') { // ..=
expr++;
@@ -590,10 +590,10 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
if (len == 0) {
semsg(_(e_invarg2), name - 1);
} else {
- if (op != NULL && vim_strchr("+-*/%", *op) != NULL) {
+ if (op != NULL && vim_strchr("+-*/%", (uint8_t)(*op)) != NULL) {
semsg(_(e_letwrong), op);
} else if (endchars != NULL
- && vim_strchr(endchars, *skipwhite(arg)) == NULL) {
+ && vim_strchr(endchars, (uint8_t)(*skipwhite(arg))) == NULL) {
emsg(_(e_letunexp));
} else if (!check_secure()) {
char *tofree = NULL;
@@ -629,7 +629,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
char *const p = (char *)find_option_end((const char **)&arg, &scope);
if (p == NULL
|| (endchars != NULL
- && vim_strchr(endchars, *skipwhite(p)) == NULL)) {
+ && vim_strchr(endchars, (uint8_t)(*skipwhite(p))) == NULL)) {
emsg(_(e_letunexp));
} else {
varnumber_T n = 0;
@@ -716,10 +716,10 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
return NULL;
}
arg++;
- if (op != NULL && vim_strchr("+-*/%", *op) != NULL) {
+ if (op != NULL && vim_strchr("+-*/%", (uint8_t)(*op)) != NULL) {
semsg(_(e_letwrong), op);
} else if (endchars != NULL
- && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL) {
+ && vim_strchr(endchars, (uint8_t)(*skipwhite(arg + 1))) == NULL) {
emsg(_(e_letunexp));
} else {
char *s;
@@ -747,7 +747,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
char *const p = get_lval(arg, tv, &lv, false, false, 0, FNE_CHECK_START);
if (p != NULL && lv.ll_name != NULL) {
- if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL) {
+ if (endchars != NULL && vim_strchr(endchars, (uint8_t)(*skipwhite(p))) == NULL) {
emsg(_(e_letunexp));
} else {
set_var_lval(&lv, p, tv, copy, is_const, op);
@@ -877,13 +877,13 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_
} else if ((lp->ll_list != NULL
// ll_list is not NULL when lvalue is not in a list, NULL lists
// yield E689.
- && var_check_lock(tv_list_locked(lp->ll_list),
- lp->ll_name,
- lp->ll_name_len))
+ && value_check_lock(tv_list_locked(lp->ll_list),
+ lp->ll_name,
+ lp->ll_name_len))
|| (lp->ll_dict != NULL
- && var_check_lock(lp->ll_dict->dv_lock,
- lp->ll_name,
- lp->ll_name_len))) {
+ && value_check_lock(lp->ll_dict->dv_lock,
+ lp->ll_name,
+ lp->ll_name_len))) {
return FAIL;
} else if (lp->ll_range) {
assert(lp->ll_list != NULL);
@@ -892,9 +892,9 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_
listitem_T *last_li = first_li;
for (;;) {
listitem_T *const li = TV_LIST_ITEM_NEXT(lp->ll_list, lp->ll_li);
- if (var_check_lock(TV_LIST_ITEM_TV(lp->ll_li)->v_lock,
- lp->ll_name,
- lp->ll_name_len)) {
+ if (value_check_lock(TV_LIST_ITEM_TV(lp->ll_li)->v_lock,
+ lp->ll_name,
+ lp->ll_name_len)) {
return false;
}
lp->ll_li = li;
@@ -976,11 +976,11 @@ int do_unlet(const char *const name, const size_t name_len, const bool forceit)
dictitem_T *const di = TV_DICT_HI2DI(hi);
if (var_check_fixed(di->di_flags, name, TV_CSTRING)
|| var_check_ro(di->di_flags, name, TV_CSTRING)
- || var_check_lock(d->dv_lock, name, TV_CSTRING)) {
+ || value_check_lock(d->dv_lock, name, TV_CSTRING)) {
return FAIL;
}
- if (var_check_lock(d->dv_lock, name, TV_CSTRING)) {
+ if (value_check_lock(d->dv_lock, name, TV_CSTRING)) {
return FAIL;
}
@@ -1023,10 +1023,6 @@ static int do_lock_var(lval_T *lp, char *name_end FUNC_ATTR_UNUSED, exarg_T *eap
bool lock = eap->cmdidx == CMD_lockvar;
int ret = OK;
- if (deep == 0) { // Nothing to do.
- return OK;
- }
-
if (lp->ll_tv == NULL) {
if (*lp->ll_name == '$') {
semsg(_(e_lock_unlock), lp->ll_name);
@@ -1050,9 +1046,13 @@ static int do_lock_var(lval_T *lp, char *name_end FUNC_ATTR_UNUSED, exarg_T *eap
} else {
di->di_flags &= (uint8_t)(~DI_FLAGS_LOCK);
}
- tv_item_lock(&di->di_tv, deep, lock, false);
+ if (deep != 0) {
+ tv_item_lock(&di->di_tv, deep, lock, false);
+ }
}
}
+ } else if (deep == 0) {
+ // nothing to do
} else if (lp->ll_range) {
listitem_T *li = lp->ll_li;
@@ -1282,12 +1282,18 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv,
return;
}
- // existing variable, need to clear the value
+ // Check in this order for backwards compatibility:
+ // - Whether the variable is read-only
+ // - Whether the variable value is locked
+ // - Whether the variable is locked
if (var_check_ro(v->di_flags, name, name_len)
- || var_check_lock(v->di_tv.v_lock, name, name_len)) {
+ || value_check_lock(v->di_tv.v_lock, name, name_len)
+ || var_check_lock(v->di_flags, name, name_len)) {
return;
}
+ // existing variable, need to clear the value
+
// Handle setting internal v: variables separately where needed to
// prevent changing the type.
if (is_vimvarht(ht)) {
@@ -1341,7 +1347,7 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv,
// Make sure dict is valid
assert(dict != NULL);
- v = xmalloc(sizeof(dictitem_T) + strlen(varname));
+ v = xmalloc(offsetof(dictitem_T, di_key) + strlen(varname) + 1);
STRCPY(v->di_key, varname);
if (hash_add(ht, (char *)v->di_key) == FAIL) {
xfree(v);
@@ -1418,6 +1424,26 @@ bool var_check_ro(const int flags, const char *name, size_t name_len)
return true;
}
+/// Return true if di_flags "flags" indicates variable "name" is locked.
+/// Also give an error message.
+bool var_check_lock(const int flags, const char *name, size_t name_len)
+{
+ if (!(flags & DI_FLAGS_LOCK)) {
+ return false;
+ }
+
+ if (name_len == TV_TRANSLATE) {
+ name = _(name);
+ name_len = strlen(name);
+ } else if (name_len == TV_CSTRING) {
+ name_len = strlen(name);
+ }
+
+ semsg(_("E1122: Variable is locked: %*s"), (int)name_len, name);
+
+ return true;
+}
+
/// Check whether variable is fixed (DI_FLAGS_FIX)
///
/// Also gives an error message.
@@ -1464,7 +1490,7 @@ bool var_wrong_func_name(const char *const name, const bool new_var)
{
// Allow for w: b: s: and t:.
// Allow autoload variable.
- if (!(vim_strchr("wbst", name[0]) != NULL && name[1] == ':')
+ if (!(vim_strchr("wbst", (uint8_t)name[0]) != NULL && name[1] == ':')
&& !ASCII_ISUPPER((name[0] != NUL && name[1] == ':') ? name[2] : name[0])
&& vim_strchr(name, '#') == NULL) {
semsg(_("E704: Funcref variable name must start with a capital: %s"), name);
diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c
index 4bcbc13534..f58a0c488a 100644
--- a/src/nvim/eval/window.c
+++ b/src/nvim/eval/window.c
@@ -12,6 +12,7 @@
#include "nvim/ascii.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/cursor.h"
#include "nvim/eval/funcs.h"
#include "nvim/eval/typval.h"
@@ -139,6 +140,8 @@ void win_findbuf(typval_T *argvars, list_T *list)
/// Find window specified by "vp" in tabpage "tp".
///
/// @param tp NULL for current tab page
+/// @return current window if "vp" is number zero.
+/// NULL if not found.
win_T *find_win_by_nr(typval_T *vp, tabpage_T *tp)
{
int nr = (int)tv_get_number_chk(vp, NULL);
diff --git a/src/nvim/eval/window.h b/src/nvim/eval/window.h
index 682a794113..995f0a55a9 100644
--- a/src/nvim/eval/window.h
+++ b/src/nvim/eval/window.h
@@ -2,9 +2,19 @@
#define NVIM_EVAL_WINDOW_H
#include <stdbool.h>
+#include <string.h>
+#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
+#include "nvim/cursor.h"
#include "nvim/eval/typval_defs.h"
+#include "nvim/globals.h"
+#include "nvim/mark.h"
+#include "nvim/option_defs.h"
+#include "nvim/os/os.h"
+#include "nvim/pos.h"
+#include "nvim/vim.h"
+#include "nvim/window.h"
/// Structure used by switch_win() to pass values to restore_win()
typedef struct {
diff --git a/src/nvim/event/libuv_process.c b/src/nvim/event/libuv_process.c
index 10a09275d9..e528d21a71 100644
--- a/src/nvim/event/libuv_process.c
+++ b/src/nvim/event/libuv_process.c
@@ -1,6 +1,7 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
+#include <assert.h>
#include <stdint.h>
#include <uv.h>
@@ -12,6 +13,7 @@
#include "nvim/log.h"
#include "nvim/macros.h"
#include "nvim/os/os.h"
+#include "nvim/ui_client.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/libuv_process.c.generated.h"
diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c
index 9dfd6f329a..1a524a56ca 100644
--- a/src/nvim/event/process.c
+++ b/src/nvim/event/process.c
@@ -20,6 +20,7 @@
#include "nvim/os/shell.h"
#include "nvim/os/time.h"
#include "nvim/rbuffer.h"
+#include "nvim/ui_client.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/process.c.generated.h"
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index c2af0e6986..437a05f61d 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -158,7 +158,7 @@ void do_ascii(const exarg_T *const eap)
char buf2[20];
buf2[0] = NUL;
- dig = (char *)get_digraph_for_char(cval);
+ dig = get_digraph_for_char(cval);
if (dig != NULL) {
iobuff_len += (size_t)vim_snprintf(IObuff + iobuff_len,
sizeof(IObuff) - iobuff_len,
@@ -206,7 +206,7 @@ void do_ascii(const exarg_T *const eap)
}
iobuff_len += (size_t)utf_char2bytes(c, IObuff + iobuff_len);
- dig = (char *)get_digraph_for_char(c);
+ dig = get_digraph_for_char(c);
if (dig != NULL) {
iobuff_len += (size_t)vim_snprintf(IObuff + iobuff_len,
sizeof(IObuff) - iobuff_len,
@@ -528,7 +528,7 @@ void ex_sort(exarg_T *eap)
emsg(_(e_noprevre));
goto sortend;
}
- regmatch.regprog = vim_regcomp((char *)last_search_pat(), RE_MAGIC);
+ regmatch.regprog = vim_regcomp(last_search_pat(), RE_MAGIC);
} else {
regmatch.regprog = vim_regcomp(p + 1, RE_MAGIC);
}
@@ -1348,7 +1348,7 @@ static char *find_pipe(const char *cmd)
}
if (*p == '"') {
inquote = !inquote;
- } else if (rem_backslash((const char_u *)p)) {
+ } else if (rem_backslash(p)) {
p++;
}
}
@@ -1420,7 +1420,7 @@ char *make_filter_cmd(char *cmd, char *itmp, char *otmp)
#else
// For shells that don't understand braces around commands, at least allow
// the use of commands in a pipe.
- xstrlcpy(buf, (char *)cmd, len);
+ xstrlcpy(buf, cmd, len);
if (itmp != NULL) {
// If there is a pipe, we have to put the '<' in front of it.
// Don't do this when 'shellquote' is not empty, otherwise the
@@ -3332,7 +3332,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
}
// new pattern and substitution
if (eap->cmd[0] == 's' && *cmd != NUL && !ascii_iswhite(*cmd)
- && vim_strchr("0123456789cegriIp|\"", *cmd) == NULL) {
+ && vim_strchr("0123456789cegriIp|\"", (uint8_t)(*cmd)) == NULL) {
// don't accept alphanumeric for separator
if (check_regexp_delim(*cmd) == FAIL) {
return 0;
@@ -3343,7 +3343,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
// //sub/r). "\&sub&" use last substitute pattern (like //sub/).
if (*cmd == '\\') {
cmd++;
- if (vim_strchr("/?&", *cmd) == NULL) {
+ if (vim_strchr("/?&", (uint8_t)(*cmd)) == NULL) {
emsg(_(e_backslash));
return 0;
}
@@ -3351,11 +3351,11 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
which_pat = RE_SEARCH; // use last '/' pattern
}
pat = ""; // empty search pattern
- delimiter = (char_u)(*cmd++); // remember delimiter character
+ delimiter = (uint8_t)(*cmd++); // remember delimiter character
has_second_delim = true;
} else { // find the end of the regexp
which_pat = RE_LAST; // use last used regexp
- delimiter = (char_u)(*cmd++); // remember delimiter character
+ delimiter = (uint8_t)(*cmd++); // remember delimiter character
pat = cmd; // remember start of search pat
cmd = skip_regexp_ex(cmd, delimiter, magic_isset(), &eap->arg, NULL, NULL);
if (cmd[0] == delimiter) { // end delimiter found
@@ -3443,7 +3443,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
return 0;
}
- if (search_regcomp((char_u *)pat, NULL, RE_SUBST, which_pat,
+ if (search_regcomp(pat, NULL, RE_SUBST, which_pat,
(cmdpreview ? 0 : SEARCH_HIS), &regmatch) == FAIL) {
if (subflags.do_error) {
emsg(_(e_invcmd));
@@ -3697,7 +3697,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
msg_putchar('\n');
xfree(prompt);
if (resp != NULL) {
- typed = (char_u)(*resp);
+ typed = (uint8_t)(*resp);
xfree(resp);
} else {
// getcmdline_prompt() returns NULL if there is no command line to return.
@@ -3895,7 +3895,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
// When it fails sublen is zero.
sublen = vim_regsub_multi(&regmatch,
sub_firstlnum - regmatch.startpos[0].lnum,
- (char_u *)sub, (char_u *)sub_firstline, 0,
+ sub, sub_firstline, 0,
REGSUB_BACKSLASH
| (magic_isset() ? REGSUB_MAGIC : 0));
textlock--;
@@ -3938,7 +3938,7 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
textlock++;
(void)vim_regsub_multi(&regmatch,
sub_firstlnum - regmatch.startpos[0].lnum,
- (char_u *)sub, (char_u *)new_end, sublen,
+ sub, new_end, sublen,
REGSUB_COPY | REGSUB_BACKSLASH
| (magic_isset() ? REGSUB_MAGIC : 0));
textlock--;
@@ -4372,7 +4372,7 @@ void ex_global(exarg_T *eap)
// "\&": use previous substitute pattern.
if (*cmd == '\\') {
cmd++;
- if (vim_strchr("/?&", *cmd) == NULL) {
+ if (vim_strchr("/?&", (uint8_t)(*cmd)) == NULL) {
emsg(_(e_backslash));
return;
}
@@ -4398,8 +4398,8 @@ void ex_global(exarg_T *eap)
}
}
- char_u *used_pat;
- if (search_regcomp((char_u *)pat, &used_pat, RE_BOTH, which_pat,
+ char *used_pat;
+ if (search_regcomp(pat, &used_pat, RE_BOTH, which_pat,
SEARCH_HIS, &regmatch) == FAIL) {
emsg(_(e_invcmd));
return;
@@ -4704,7 +4704,7 @@ char *skip_vimgrep_pat(char *p, char **s, int *flags)
if (s != NULL) {
*s = p + 1;
}
- c = (char_u)(*p);
+ c = (uint8_t)(*p);
p = skip_regexp(p + 1, c, true);
if (*p != c) {
return NULL;
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index 68db03bd7d..c8b6ceab69 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -2387,7 +2387,7 @@ module.cmds = {
},
{
command='scriptnames',
- flags=bit.bor(BANG, RANGE, COUNT, TRLBAR, CMDWIN, LOCK_OK),
+ flags=bit.bor(BANG, FILES, RANGE, COUNT, TRLBAR, CMDWIN, LOCK_OK),
addr_type='ADDR_OTHER',
func='ex_scriptnames',
},
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index e11dd0a2f6..a24e8458a6 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -369,7 +369,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
// Get the function or script name and the address where the next breakpoint
// line and the debug tick for a function or script are stored.
if (getline_is_func) {
- fname = (char *)func_name(real_cookie);
+ fname = func_name(real_cookie);
breakpoint = func_breakpoint(real_cookie);
dbg_tick = func_dbg_tick(real_cookie);
} else if (getline_equal(fgetline, cookie, getsourceline)) {
@@ -919,7 +919,7 @@ static char *get_loop_line(int c, void *cookie, int indent, bool do_concat)
char *line;
// First time inside the ":while"/":for": get line normally.
if (cp->getline == NULL) {
- line = (char *)getcmdline(c, 0L, indent, do_concat);
+ line = getcmdline(c, 0L, indent, do_concat);
} else {
line = cp->getline(c, cp->cookie, indent, do_concat);
}
@@ -2852,7 +2852,7 @@ bool checkforcmd(char **pp, const char *cmd, int len)
break;
}
}
- if (i >= len && !isalpha((*pp)[i])) {
+ if (i >= len && !ASCII_ISALPHA((*pp)[i])) {
*pp = skipwhite(*pp + i);
return true;
}
@@ -2877,7 +2877,7 @@ static void append_command(char *cmd)
STRCAT(IObuff, ": ");
d = IObuff + strlen(IObuff);
while (*s != NUL && d - IObuff + 5 < IOSIZE) {
- if ((char_u)s[0] == 0xc2 && (char_u)s[1] == 0xa0) {
+ if ((uint8_t)s[0] == 0xc2 && (uint8_t)s[1] == 0xa0) {
s += 2;
STRCPY(d, "<a0>");
d += 4;
@@ -2890,6 +2890,33 @@ static void append_command(char *cmd)
*d = NUL;
}
+/// Return true and set "*idx" if "p" points to a one letter command.
+/// - The 'k' command can directly be followed by any character.
+/// - The 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
+/// but :sre[wind] is another command, as are :scr[iptnames],
+/// :scs[cope], :sim[alt], :sig[ns] and :sil[ent].
+static int one_letter_cmd(const char *p, cmdidx_T *idx)
+{
+ if (*p == 'k') {
+ *idx = CMD_k;
+ return true;
+ }
+ if (p[0] == 's'
+ && ((p[1] == 'c'
+ && (p[2] == NUL
+ || (p[2] != 's' && p[2] != 'r'
+ && (p[3] == NUL
+ || (p[3] != 'i' && p[4] != 'p')))))
+ || p[1] == 'g'
+ || (p[1] == 'i' && p[2] != 'm' && p[2] != 'l' && p[2] != 'g')
+ || p[1] == 'I'
+ || (p[1] == 'r' && p[2] != 'e'))) {
+ *idx = CMD_substitute;
+ return true;
+ }
+ return false;
+}
+
/// Find an Ex command by its name, either built-in or user.
/// Start of the name can be found at eap->cmd.
/// Sets eap->cmdidx and returns a pointer to char after the command name.
@@ -2900,27 +2927,8 @@ char *find_ex_command(exarg_T *eap, int *full)
FUNC_ATTR_NONNULL_ARG(1)
{
// Isolate the command and search for it in the command table.
- // Exceptions:
- // - the 'k' command can directly be followed by any character.
- // - the 's' command can be followed directly by 'c', 'g', 'i', 'I' or 'r'
- // but :sre[wind] is another command, as are :scr[iptnames],
- // :scs[cope], :sim[alt], :sig[ns] and :sil[ent].
- // - the "d" command can directly be followed by 'l' or 'p' flag.
char *p = eap->cmd;
- if (*p == 'k') {
- eap->cmdidx = CMD_k;
- p++;
- } else if (p[0] == 's'
- && ((p[1] == 'c'
- && (p[2] == NUL
- || (p[2] != 's' && p[2] != 'r'
- && (p[3] == NUL
- || (p[3] != 'i' && p[4] != 'p')))))
- || p[1] == 'g'
- || (p[1] == 'i' && p[2] != 'm' && p[2] != 'l' && p[2] != 'g')
- || p[1] == 'I'
- || (p[1] == 'r' && p[2] != 'e'))) {
- eap->cmdidx = CMD_substitute;
+ if (one_letter_cmd(p, &eap->cmdidx)) {
p++;
} else {
while (ASCII_ISALPHA(*p)) {
@@ -2934,10 +2942,11 @@ char *find_ex_command(exarg_T *eap, int *full)
}
// check for non-alpha command
- if (p == eap->cmd && vim_strchr("@!=><&~#", *p) != NULL) {
+ if (p == eap->cmd && vim_strchr("@!=><&~#", (uint8_t)(*p)) != NULL) {
p++;
}
int len = (int)(p - eap->cmd);
+ // The "d" command can directly be followed by 'l' or 'p' flag.
if (*eap->cmd == 'd' && (p[-1] == 'l' || p[-1] == 'p')) {
// Check for ":dl", ":dell", etc. to ":deletel": that's
// :delete with the 'l' flag. Same for 'p'.
@@ -2958,7 +2967,7 @@ char *find_ex_command(exarg_T *eap, int *full)
}
if (ASCII_ISLOWER(eap->cmd[0])) {
- const int c1 = (char_u)eap->cmd[0];
+ const int c1 = (uint8_t)eap->cmd[0];
const int c2 = len == 1 ? NUL : eap->cmd[1];
if (command_count != CMD_SIZE) {
@@ -3135,9 +3144,11 @@ cmdidx_T excmd_get_cmdidx(const char *cmd, size_t len)
{
cmdidx_T idx;
- for (idx = (cmdidx_T)0; (int)idx < CMD_SIZE; idx = (cmdidx_T)((int)idx + 1)) {
- if (strncmp(cmdnames[(int)idx].cmd_name, cmd, len) == 0) {
- break;
+ if (!one_letter_cmd(cmd, &idx)) {
+ for (idx = (cmdidx_T)0; (int)idx < CMD_SIZE; idx = (cmdidx_T)((int)idx + 1)) {
+ if (strncmp(cmdnames[(int)idx].cmd_name, cmd, len) == 0) {
+ break;
+ }
}
}
@@ -3161,7 +3172,7 @@ uint32_t excmd_get_argt(cmdidx_T idx)
/// @return the "cmd" pointer advanced to beyond the range.
char *skip_range(const char *cmd, int *ctx)
{
- while (vim_strchr(" \t0123456789.$%'/?-+,;\\", *cmd) != NULL) {
+ while (vim_strchr(" \t0123456789.$%'/?-+,;\\", (uint8_t)(*cmd)) != NULL) {
if (*cmd == '\\') {
if (cmd[1] == '?' || cmd[1] == '/' || cmd[1] == '&') {
cmd++;
@@ -3350,7 +3361,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
case '/':
case '?': // '/' or '?' - search
- c = (char_u)(*cmd++);
+ c = (uint8_t)(*cmd++);
if (addr_type != ADDR_LINES) {
addr_error(addr_type);
cmd = NULL;
@@ -3423,7 +3434,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
pos.coladd = 0;
if (searchit(curwin, curbuf, &pos, NULL,
*cmd == '?' ? BACKWARD : FORWARD,
- (char_u *)"", 1L, SEARCH_MSG, i, NULL) != FAIL) {
+ "", 1L, SEARCH_MSG, i, NULL) != FAIL) {
lnum = pos.lnum;
} else {
cmd = NULL;
@@ -3484,7 +3495,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
if (ascii_isdigit(*cmd)) {
i = '+'; // "number" is same as "+number"
} else {
- i = (char_u)(*cmd++);
+ i = (uint8_t)(*cmd++);
}
if (!ascii_isdigit(*cmd)) { // '+' is '+1'
n = 1;
@@ -3531,7 +3542,7 @@ error:
/// Get flags from an Ex command argument.
static void get_flags(exarg_T *eap)
{
- while (vim_strchr("lp#", *eap->arg) != NULL) {
+ while (vim_strchr("lp#", (uint8_t)(*eap->arg)) != NULL) {
if (*eap->arg == 'l') {
eap->flags |= EXFLAG_LIST;
} else if (*eap->arg == 'p') {
@@ -3699,7 +3710,7 @@ char *replace_makeprg(exarg_T *eap, char *arg, char **cmdlinep)
if ((eap->cmdidx == CMD_make || eap->cmdidx == CMD_lmake || isgrep)
&& !grep_internal(eap->cmdidx)) {
const char *program = isgrep ? (*curbuf->b_p_gp == NUL ? p_gp : curbuf->b_p_gp)
- : (*curbuf->b_p_mp == NUL ? (char *)p_mp : curbuf->b_p_mp);
+ : (*curbuf->b_p_mp == NUL ? p_mp : curbuf->b_p_mp);
arg = skipwhite(arg);
@@ -3748,7 +3759,7 @@ int expand_filename(exarg_T *eap, char **cmdlinep, char **errormsgp)
}
// Quick check if this cannot be the start of a special string.
// Also removes backslash before '%', '#' and '<'.
- if (vim_strchr("%#<", *p) == NULL) {
+ if (vim_strchr("%#<", (uint8_t)(*p)) == NULL) {
p++;
continue;
}
@@ -3756,8 +3767,8 @@ int expand_filename(exarg_T *eap, char **cmdlinep, char **errormsgp)
// Try to find a match at this position.
size_t srclen;
int escaped;
- char *repl = (char *)eval_vars((char_u *)p, (char_u *)eap->arg, &srclen, &(eap->do_ecmd_lnum),
- errormsgp, &escaped, true);
+ char *repl = eval_vars(p, eap->arg, &srclen, &(eap->do_ecmd_lnum),
+ errormsgp, &escaped, true);
if (*errormsgp != NULL) { // error detected
return FAIL;
}
@@ -3801,8 +3812,8 @@ int expand_filename(exarg_T *eap, char **cmdlinep, char **errormsgp)
#endif
for (l = repl; *l; l++) {
- if (vim_strchr((char *)ESCAPE_CHARS, *l) != NULL) {
- l = vim_strsave_escaped(repl, (char *)ESCAPE_CHARS);
+ if (vim_strchr(ESCAPE_CHARS, (uint8_t)(*l)) != NULL) {
+ l = vim_strsave_escaped(repl, ESCAPE_CHARS);
xfree(repl);
repl = l;
break;
@@ -3857,7 +3868,7 @@ int expand_filename(exarg_T *eap, char **cmdlinep, char **errormsgp)
backslash_halve(eap->arg);
}
#else
- backslash_halve((char_u *)eap->arg);
+ backslash_halve(eap->arg);
#endif
if (has_wildcards) {
@@ -4033,15 +4044,15 @@ char *skip_cmd_arg(char *p, int rembs)
return p;
}
-int get_bad_opt(const char_u *p, exarg_T *eap)
+int get_bad_opt(const char *p, exarg_T *eap)
FUNC_ATTR_NONNULL_ALL
{
if (STRICMP(p, "keep") == 0) {
eap->bad_char = BAD_KEEP;
} else if (STRICMP(p, "drop") == 0) {
eap->bad_char = BAD_DROP;
- } else if (MB_BYTE2LEN(*p) == 1 && p[1] == NUL) {
- eap->bad_char = *p;
+ } else if (MB_BYTE2LEN((uint8_t)(*p)) == 1 && p[1] == NUL) {
+ eap->bad_char = (uint8_t)(*p);
} else {
return FAIL;
}
@@ -4118,7 +4129,7 @@ static int getargopt(exarg_T *eap)
if (check_ff_value(eap->cmd + eap->force_ff) == FAIL) {
return FAIL;
}
- eap->force_ff = (char_u)eap->cmd[eap->force_ff];
+ eap->force_ff = (uint8_t)eap->cmd[eap->force_ff];
} else if (pp == &eap->force_enc) {
// Make 'fileencoding' lower case.
for (char *p = eap->cmd + eap->force_enc; *p != NUL; p++) {
@@ -4127,7 +4138,7 @@ static int getargopt(exarg_T *eap)
} else {
// Check ++bad= argument. Must be a single-byte character, "keep" or
// "drop".
- if (get_bad_opt((char_u *)eap->cmd + bad_char_idx, eap) == FAIL) {
+ if (get_bad_opt(eap->cmd + bad_char_idx, eap) == FAIL) {
return FAIL;
}
}
@@ -4965,8 +4976,8 @@ void ex_splitview(exarg_T *eap)
}
if (eap->cmdidx == CMD_sfind || eap->cmdidx == CMD_tabfind) {
- fname = (char *)find_file_in_path(eap->arg, strlen(eap->arg),
- FNAME_MESS, true, curbuf->b_ffname);
+ fname = find_file_in_path(eap->arg, strlen(eap->arg),
+ FNAME_MESS, true, curbuf->b_ffname);
if (fname == NULL) {
goto theend;
}
@@ -4976,7 +4987,7 @@ void ex_splitview(exarg_T *eap)
// Either open new tab page or split the window.
if (use_tab) {
if (win_new_tabpage(cmdmod.cmod_tab != 0 ? cmdmod.cmod_tab : eap->addr_count == 0
- ? 0 : (int)eap->line2 + 1, (char_u *)eap->arg) != FAIL) {
+ ? 0 : (int)eap->line2 + 1, eap->arg) != FAIL) {
do_exedit(eap, old_curwin);
apply_autocmds(EVENT_TABNEWENTERED, NULL, NULL, false, curbuf);
@@ -5158,15 +5169,15 @@ static void ex_resize(exarg_T *eap)
/// ":find [+command] <file>" command.
static void ex_find(exarg_T *eap)
{
- char *fname = (char *)find_file_in_path(eap->arg, strlen(eap->arg),
- FNAME_MESS, true, curbuf->b_ffname);
+ char *fname = find_file_in_path(eap->arg, strlen(eap->arg),
+ FNAME_MESS, true, curbuf->b_ffname);
if (eap->addr_count > 0) {
// Repeat finding the file "count" times. This matters when it
// appears several times in the path.
linenr_T count = eap->line2;
while (fname != NULL && --count > 0) {
xfree(fname);
- fname = (char *)find_file_in_path(NULL, 0, FNAME_MESS, false, curbuf->b_ffname);
+ fname = find_file_in_path(NULL, 0, FNAME_MESS, false, curbuf->b_ffname);
}
}
@@ -5238,9 +5249,9 @@ void do_exedit(exarg_T *eap, win_T *old_curwin)
old_curwin == NULL ? curwin : NULL);
} else if ((eap->cmdidx != CMD_split && eap->cmdidx != CMD_vsplit)
|| *eap->arg != NUL) {
- // Can't edit another file when "curbuf->b_ro_locked" is set. Only ":edit"
- // can bring us here, others are stopped earlier.
- if (*eap->arg != NUL && curbuf_locked()) {
+ // Can't edit another file when "textlock" or "curbuf->b_ro_locked" is set.
+ // Only ":edit" or ":script" can bring us here, others are stopped earlier.
+ if (*eap->arg != NUL && text_or_buf_locked()) {
return;
}
n = readonlymode;
@@ -5961,18 +5972,18 @@ static void ex_undo(exarg_T *eap)
static void ex_wundo(exarg_T *eap)
{
- char hash[UNDO_HASH_SIZE];
+ uint8_t hash[UNDO_HASH_SIZE];
- u_compute_hash(curbuf, (char_u *)hash);
- u_write_undo(eap->arg, eap->forceit, curbuf, (char_u *)hash);
+ u_compute_hash(curbuf, hash);
+ u_write_undo(eap->arg, eap->forceit, curbuf, hash);
}
static void ex_rundo(exarg_T *eap)
{
- char hash[UNDO_HASH_SIZE];
+ uint8_t hash[UNDO_HASH_SIZE];
- u_compute_hash(curbuf, (char_u *)hash);
- u_read_undo(eap->arg, (char_u *)hash, NULL);
+ u_compute_hash(curbuf, hash);
+ u_read_undo(eap->arg, hash, NULL);
}
/// ":redo".
@@ -5991,7 +6002,7 @@ static void ex_later(exarg_T *eap)
if (*p == NUL) {
count = 1;
- } else if (isdigit(*p)) {
+ } else if (isdigit((uint8_t)(*p))) {
count = getdigits_long(&p, false, 0);
switch (*p) {
case 's':
@@ -6049,7 +6060,7 @@ static void ex_redir(exarg_T *eap)
close_redir();
arg++;
if (valid_yank_reg(*arg, true) && *arg != '_') {
- redir_reg = (char_u)(*arg++);
+ redir_reg = (uint8_t)(*arg++);
if (*arg == '>' && arg[1] == '>') { // append
arg += 2;
} else {
@@ -6714,8 +6725,8 @@ ssize_t find_cmdline_var(const char *src, size_t *usedlen)
/// @return an allocated string if a valid match was found.
/// Returns NULL if no match was found. "usedlen" then still contains the
/// number of characters to skip.
-char_u *eval_vars(char_u *src, const char_u *srcstart, size_t *usedlen, linenr_T *lnump,
- char **errormsg, int *escaped, bool empty_is_error)
+char *eval_vars(char *src, const char *srcstart, size_t *usedlen, linenr_T *lnump, char **errormsg,
+ int *escaped, bool empty_is_error)
{
char *result;
char *resultbuf = NULL;
@@ -6731,7 +6742,7 @@ char_u *eval_vars(char_u *src, const char_u *srcstart, size_t *usedlen, linenr_T
}
// Check if there is something to do.
- ssize_t spec_idx = find_cmdline_var((char *)src, usedlen);
+ ssize_t spec_idx = find_cmdline_var(src, usedlen);
if (spec_idx < 0) { // no match
*usedlen = 1;
return NULL;
@@ -6789,16 +6800,16 @@ char_u *eval_vars(char_u *src, const char_u *srcstart, size_t *usedlen, linenr_T
skip_mod = true;
break;
}
- char *s = (char *)src + 1;
+ char *s = src + 1;
if (*s == '<') { // "#<99" uses v:oldfiles.
s++;
}
int i = getdigits_int(&s, false, 0);
- if ((char_u *)s == src + 2 && src[1] == '-') {
+ if (s == src + 2 && src[1] == '-') {
// just a minus sign, don't skip over it
s--;
}
- *usedlen = (size_t)((char_u *)s - src); // length of what we expand
+ *usedlen = (size_t)(s - src); // length of what we expand
if (src[1] == '<' && i != 0) {
if (*usedlen < 2) {
@@ -6834,7 +6845,7 @@ char_u *eval_vars(char_u *src, const char_u *srcstart, size_t *usedlen, linenr_T
break;
case SPEC_CFILE: // file name under cursor
- result = (char *)file_name_at_cursor(FNAME_MESS|FNAME_HYP, 1L, NULL);
+ result = file_name_at_cursor(FNAME_MESS|FNAME_HYP, 1L, NULL);
if (result == NULL) {
*errormsg = "";
return NULL;
@@ -6844,7 +6855,7 @@ char_u *eval_vars(char_u *src, const char_u *srcstart, size_t *usedlen, linenr_T
case SPEC_AFILE: // file name for autocommand
if (autocmd_fname != NULL
- && !path_is_absolute((char_u *)autocmd_fname)
+ && !path_is_absolute(autocmd_fname)
// For CmdlineEnter and related events, <afile> is not a path! #9348
&& !strequal("/", autocmd_fname)) {
// Still need to turn the fname into a full path. It was
@@ -6951,7 +6962,7 @@ char_u *eval_vars(char_u *src, const char_u *srcstart, size_t *usedlen, linenr_T
resultlen = (size_t)(s - result);
}
} else if (!skip_mod) {
- valid |= modify_fname((char *)src, tilde_file, usedlen, &result,
+ valid |= modify_fname(src, tilde_file, usedlen, &result,
&resultbuf, &resultlen);
if (result == NULL) {
*errormsg = "";
@@ -6974,7 +6985,7 @@ char_u *eval_vars(char_u *src, const char_u *srcstart, size_t *usedlen, linenr_T
result = xstrnsave(result, resultlen);
}
xfree(resultbuf);
- return (char_u *)result;
+ return result;
}
/// Expand the <sfile> string in "arg".
@@ -6991,8 +7002,7 @@ char *expand_sfile(char *arg)
// replace "<sfile>" with the sourced file name, and do ":" stuff
size_t srclen;
char *errormsg;
- char *repl = (char *)eval_vars((char_u *)p, (char_u *)result, &srclen, NULL, &errormsg, NULL,
- true);
+ char *repl = eval_vars(p, result, &srclen, NULL, &errormsg, NULL, true);
if (errormsg != NULL) {
if (*errormsg) {
emsg(errormsg);
diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c
index 6450892e39..f76e60f6c5 100644
--- a/src/nvim/ex_eval.c
+++ b/src/nvim/ex_eval.c
@@ -449,8 +449,8 @@ static int throw_exception(void *value, except_type_T type, char *cmdname)
// when no active try block is found, see do_cmdline().
if (type == ET_USER) {
if (strncmp(value, "Vim", 3) == 0
- && (((char_u *)value)[3] == NUL || ((char_u *)value)[3] == ':'
- || ((char_u *)value)[3] == '(')) {
+ && (((char *)value)[3] == NUL || ((char *)value)[3] == ':'
+ || ((char *)value)[3] == '(')) {
emsg(_("E608: Cannot :throw exceptions with 'Vim' prefix"));
goto fail;
}
@@ -1150,7 +1150,7 @@ void ex_throw(exarg_T *eap)
// On error or when an exception is thrown during argument evaluation, do
// not throw.
if (!eap->skip && value != NULL) {
- if (throw_exception((char_u *)value, ET_USER, NULL) == FAIL) {
+ if (throw_exception(value, ET_USER, NULL) == FAIL) {
xfree(value);
} else {
do_throw(eap->cstack);
@@ -1372,8 +1372,7 @@ void ex_catch(exarg_T *eap)
//
prev_got_int = got_int;
got_int = false;
- caught = vim_regexec_nl(&regmatch, (char_u *)current_exception->value,
- (colnr_T)0);
+ caught = vim_regexec_nl(&regmatch, current_exception->value, (colnr_T)0);
got_int |= prev_got_int;
vim_regfree(regmatch.regprog);
}
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 72208c976f..76c3680742 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -274,7 +274,7 @@ static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_s
parse_command_modifiers(&ea, &dummy, &dummy_cmdmod, true);
cmd = skip_range(ea.cmd, NULL);
- if (vim_strchr("sgvl", *cmd) == NULL) {
+ if (vim_strchr("sgvl", (uint8_t)(*cmd)) == NULL) {
goto theend;
}
@@ -381,7 +381,7 @@ static void may_do_incsearch_highlighting(int firstc, long count, incsearch_stat
proftime_T tm;
int skiplen, patlen;
char next_char;
- char_u use_last_pat;
+ bool use_last_pat;
int search_delim;
// Parsing range may already set the last search pattern.
@@ -558,7 +558,7 @@ static int may_add_char_to_search(int firstc, int *c, incsearch_state_T *s)
// command line has no uppercase characters, convert
// the character to lowercase
if (p_ic && p_scs
- && !pat_has_uppercase((char_u *)ccline.cmdbuff + skiplen)) {
+ && !pat_has_uppercase(ccline.cmdbuff + skiplen)) {
*c = mb_tolower(*c);
}
if (*c == search_delim
@@ -725,7 +725,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool clea
if (ccline.input_fn) {
s->xpc.xp_context = ccline.xp_context;
s->xpc.xp_pattern = ccline.cmdbuff;
- s->xpc.xp_arg = (char *)ccline.xp_arg;
+ s->xpc.xp_arg = ccline.xp_arg;
}
// Avoid scrolling when called by a recursive do_cmdline(), e.g. when
@@ -773,7 +773,8 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool clea
tl_ret = try_leave(&tstate, &err);
if (!tl_ret && ERROR_SET(&err)) {
msg_putchar('\n');
- msg_printf_attr(HL_ATTR(HLF_E)|MSG_HIST, (char *)e_autocmd_err, err.msg);
+ msg_scroll = true;
+ msg_puts_attr(err.msg, HL_ATTR(HLF_E)|MSG_HIST);
api_clear_error(&err);
redrawcmd();
}
@@ -881,7 +882,7 @@ static uint8_t *command_line_enter(int firstc, long count, int indent, bool clea
if (!tl_ret && ERROR_SET(&err)) {
msg_putchar('\n');
- semsg(e_autocmd_err, err.msg);
+ emsg(err.msg);
did_emsg = false;
api_clear_error(&err);
}
@@ -907,7 +908,7 @@ theend:
xfree(ccline.last_colors.cmdbuff);
kv_destroy(ccline.last_colors.colors);
- char_u *p = (char_u *)ccline.cmdbuff;
+ char *p = ccline.cmdbuff;
if (ui_has(kUICmdline)) {
ui_call_cmdline_hide(ccline.level);
@@ -922,7 +923,7 @@ theend:
ccline.cmdbuff = NULL;
}
- return p;
+ return (uint8_t *)p;
}
static int command_line_check(VimState *state)
@@ -1234,10 +1235,20 @@ static int command_line_execute(VimState *state, int key)
}
}
+ // The wildmenu is cleared if the pressed key is not used for
+ // navigating the wild menu (i.e. the key is not 'wildchar' or
+ // 'wildcharm' or Ctrl-N or Ctrl-P or Ctrl-A or Ctrl-L).
+ // If the popup menu is displayed, then PageDown and PageUp keys are
+ // also used to navigate the menu.
+ bool end_wildmenu = (!(s->c == p_wc && KeyTyped) && s->c != p_wcm && s->c != Ctrl_Z
+ && s->c != Ctrl_N && s->c != Ctrl_P && s->c != Ctrl_A
+ && s->c != Ctrl_L);
+ end_wildmenu = end_wildmenu && (!cmdline_pum_active()
+ || (s->c != K_PAGEDOWN && s->c != K_PAGEUP
+ && s->c != K_KPAGEDOWN && s->c != K_KPAGEUP));
+
// free expanded names when finished walking through matches
- if (!(s->c == p_wc && KeyTyped) && s->c != p_wcm && s->c != Ctrl_Z
- && s->c != Ctrl_N && s->c != Ctrl_P && s->c != Ctrl_A
- && s->c != Ctrl_L) {
+ if (end_wildmenu) {
command_line_end_wildmenu(s);
}
@@ -1368,7 +1379,7 @@ static int may_do_command_line_next_incsearch(int firstc, long count, incsearch_
char save;
if (search_delim == ccline.cmdbuff[skiplen]) {
- pat = (char *)last_search_pattern();
+ pat = last_search_pattern();
if (pat == NULL) {
restore_last_search_pattern();
return FAIL;
@@ -1398,7 +1409,7 @@ static int may_do_command_line_next_incsearch(int firstc, long count, incsearch_
pat[patlen] = NUL;
int found = searchit(curwin, curbuf, &t, NULL,
next_match ? FORWARD : BACKWARD,
- (char_u *)pat, count, search_flags,
+ pat, count, search_flags,
RE_SEARCH, NULL);
emsg_off--;
pat[patlen] = save;
@@ -1463,7 +1474,7 @@ static int command_line_erase_chars(CommandLineState *s)
}
if (s->c == K_DEL) {
- ccline.cmdpos += mb_off_next((char_u *)ccline.cmdbuff,
+ ccline.cmdpos += mb_off_next(ccline.cmdbuff,
ccline.cmdbuff + ccline.cmdpos);
}
@@ -1546,9 +1557,9 @@ static void command_line_toggle_langmap(CommandLineState *s)
if (s->b_im_ptr != NULL) {
if (s->b_im_ptr == &curbuf->b_p_iminsert) {
- set_iminsert_global();
+ set_iminsert_global(curbuf);
} else {
- set_imsearch_global();
+ set_imsearch_global(curbuf);
}
}
ui_cursor_shape(); // may show different cursor shape
@@ -2000,8 +2011,8 @@ static int command_line_handle_key(CommandLineState *s)
case Ctrl_N: // next match
case Ctrl_P: // previous match
if (s->xpc.xp_numfiles > 0) {
- if (nextwild(&s->xpc, (s->c == Ctrl_P) ? WILD_PREV : WILD_NEXT,
- 0, s->firstc != '@') == FAIL) {
+ const int wild_type = (s->c == Ctrl_P) ? WILD_PREV : WILD_NEXT;
+ if (nextwild(&s->xpc, wild_type, 0, s->firstc != '@') == FAIL) {
break;
}
return command_line_not_changed(s);
@@ -2016,13 +2027,26 @@ static int command_line_handle_key(CommandLineState *s)
case K_KPAGEUP:
case K_PAGEDOWN:
case K_KPAGEDOWN:
- switch (command_line_browse_history(s)) {
- case CMDLINE_CHANGED:
- return command_line_changed(s);
- case GOTO_NORMAL_MODE:
- return 0;
- default:
+ if (cmdline_pum_active()
+ && (s->c == K_PAGEUP || s->c == K_PAGEDOWN
+ || s->c == K_KPAGEUP || s->c == K_KPAGEDOWN)) {
+ // If the popup menu is displayed, then PageUp and PageDown
+ // are used to scroll the menu.
+ const int wild_type =
+ (s->c == K_PAGEDOWN || s->c == K_KPAGEDOWN) ? WILD_PAGEDOWN : WILD_PAGEUP;
+ if (nextwild(&s->xpc, wild_type, 0, s->firstc != '@') == FAIL) {
+ break;
+ }
return command_line_not_changed(s);
+ } else {
+ switch (command_line_browse_history(s)) {
+ case CMDLINE_CHANGED:
+ return command_line_changed(s);
+ case GOTO_NORMAL_MODE:
+ return 0;
+ default:
+ return command_line_not_changed(s);
+ }
}
case Ctrl_G: // next match
@@ -2141,7 +2165,7 @@ static bool empty_pattern_magic(char *p, size_t len, magic_T magic_val)
{
// remove trailing \v and the like
while (len >= 2 && p[len - 2] == '\\'
- && vim_strchr("mMvVcCZ", p[len - 1]) != NULL) {
+ && vim_strchr("mMvVcCZ", (uint8_t)p[len - 1]) != NULL) {
len -= 2;
}
@@ -2521,7 +2545,8 @@ static void do_autocmd_cmdlinechanged(int firstc)
bool tl_ret = try_leave(&tstate, &err);
if (!tl_ret && ERROR_SET(&err)) {
msg_putchar('\n');
- msg_printf_attr(HL_ATTR(HLF_E)|MSG_HIST, (char *)e_autocmd_err, err.msg);
+ msg_scroll = true;
+ msg_puts_attr(err.msg, HL_ATTR(HLF_E)|MSG_HIST);
api_clear_error(&err);
redrawcmd();
}
@@ -2600,9 +2625,9 @@ static void abandon_cmdline(void)
///
/// @param count only used for incremental search
/// @param indent indent for inside conditionals
-char_u *getcmdline(int firstc, long count, int indent, bool do_concat FUNC_ATTR_UNUSED)
+char *getcmdline(int firstc, long count, int indent, bool do_concat FUNC_ATTR_UNUSED)
{
- return command_line_enter(firstc, count, indent, true);
+ return (char *)command_line_enter(firstc, count, indent, true);
}
/// Get a command line with a prompt
@@ -2635,10 +2660,10 @@ char *getcmdline_prompt(const int firstc, const char *const prompt, const int at
CLEAR_FIELD(ccline);
}
ccline.prompt_id = last_prompt_id++;
- ccline.cmdprompt = (char_u *)prompt;
+ ccline.cmdprompt = (char *)prompt;
ccline.cmdattr = attr;
ccline.xp_context = xp_context;
- ccline.xp_arg = (char_u *)xp_arg;
+ ccline.xp_arg = (char *)xp_arg;
ccline.input_fn = (firstc == '@');
ccline.highlight_callback = highlight_callback;
@@ -2662,12 +2687,6 @@ char *getcmdline_prompt(const int firstc, const char *const prompt, const int at
return ret;
}
-// Return current cmdline prompt
-char_u *get_cmdprompt(void)
-{
- return ccline.cmdprompt;
-}
-
/// Read the 'wildmode' option, fill wim_flags[].
int check_opt_wim(void)
{
@@ -2847,7 +2866,7 @@ char *getexline(int c, void *cookie, int indent, bool do_concat)
(void)vgetc();
}
- return (char *)getcmdline(c, 1L, indent, do_concat);
+ return getcmdline(c, 1L, indent, do_concat);
}
bool cmdline_overstrike(void)
@@ -2885,7 +2904,7 @@ void realloc_cmdbuff(int len)
return; // no need to resize
}
- char_u *p = (char_u *)ccline.cmdbuff;
+ char *p = ccline.cmdbuff;
alloc_cmdbuff(len); // will get some more
// There isn't always a NUL after the command, but it may need to be
// there, thus copy up to the NUL and add a NUL.
@@ -2897,7 +2916,7 @@ void realloc_cmdbuff(int len)
&& ccline.xpc->xp_pattern != NULL
&& ccline.xpc->xp_context != EXPAND_NOTHING
&& ccline.xpc->xp_context != EXPAND_UNSUCCESSFUL) {
- int i = (int)((char_u *)ccline.xpc->xp_pattern - p);
+ int i = (int)(ccline.xpc->xp_pattern - p);
// If xp_pattern points inside the old cmdbuff it needs to be adjusted
// to point into the newly allocated memory.
@@ -3232,10 +3251,10 @@ static void draw_cmdline(int start, int len)
bool do_arabicshape = false;
int mb_l;
for (int i = start; i < start + len; i += mb_l) {
- char_u *p = (char_u *)ccline.cmdbuff + i;
+ char *p = ccline.cmdbuff + i;
int u8cc[MAX_MCO];
- int u8c = utfc_ptr2char_len((char *)p, u8cc, start + len - i);
- mb_l = utfc_ptr2len_len((char *)p, start + len - i);
+ int u8c = utfc_ptr2char_len(p, u8cc, start + len - i);
+ mb_l = utfc_ptr2len_len(p, start + len - i);
if (ARABIC_CHAR(u8c)) {
do_arabicshape = true;
break;
@@ -3268,10 +3287,10 @@ static void draw_cmdline(int start, int len)
int prev_c = 0;
int prev_c1 = 0;
for (int i = start; i < start + len; i += mb_l) {
- char_u *p = (char_u *)ccline.cmdbuff + i;
+ char *p = ccline.cmdbuff + i;
int u8cc[MAX_MCO];
- int u8c = utfc_ptr2char_len((char *)p, u8cc, start + len - i);
- mb_l = utfc_ptr2len_len((char *)p, start + len - i);
+ int u8c = utfc_ptr2char_len(p, u8cc, start + len - i);
+ mb_l = utfc_ptr2len_len(p, start + len - i);
if (ARABIC_CHAR(u8c)) {
int pc;
int pc1 = 0;
@@ -3285,7 +3304,7 @@ static void draw_cmdline(int start, int len)
if (i + mb_l >= start + len) {
nc = NUL;
} else {
- nc = utf_ptr2char((char *)p + mb_l);
+ nc = utf_ptr2char(p + mb_l);
}
} else {
// Displaying from left to right.
@@ -3294,7 +3313,7 @@ static void draw_cmdline(int start, int len)
} else {
int pcc[MAX_MCO];
- pc = utfc_ptr2char_len((char *)p + mb_l, pcc, start + len - i - mb_l);
+ pc = utfc_ptr2char_len(p + mb_l, pcc, start + len - i - mb_l);
pc1 = pcc[0];
}
nc = prev_c;
@@ -3344,7 +3363,7 @@ static void ui_ext_cmdline_show(CmdlineInfo *line)
if (cmdline_star) {
content = arena_array(&arena, 1);
size_t len = 0;
- for (char_u *p = (char_u *)ccline.cmdbuff; *p; MB_PTR_ADV(p)) {
+ for (char *p = ccline.cmdbuff; *p; MB_PTR_ADV(p)) {
len++;
}
char *buf = arena_alloc(&arena, len, false);
@@ -3375,7 +3394,7 @@ static void ui_ext_cmdline_show(CmdlineInfo *line)
char charbuf[2] = { (char)line->cmdfirstc, 0 };
ui_call_cmdline_show(content, line->cmdpos,
cstr_as_string(charbuf),
- cstr_as_string((char *)(line->cmdprompt)),
+ cstr_as_string((line->cmdprompt)),
line->cmdindent,
line->level);
if (line->special_char) {
@@ -3657,7 +3676,7 @@ static void restore_cmdline(CmdlineInfo *ccp)
static bool cmdline_paste(int regname, bool literally, bool remcr)
{
char *arg;
- char_u *p;
+ char *p;
bool allocated;
// check for valid regname; also accept special characters for CTRL-R in
@@ -3689,7 +3708,7 @@ static bool cmdline_paste(int regname, bool literally, bool remcr)
// When 'incsearch' is set and CTRL-R CTRL-W used: skip the duplicate
// part of the word.
- p = (char_u *)arg;
+ p = arg;
if (p_is && regname == Ctrl_W) {
char *w;
int len;
@@ -3722,19 +3741,19 @@ static bool cmdline_paste(int regname, bool literally, bool remcr)
// When "literally" is true, insert literally.
// When "literally" is false, insert as typed, but don't leave the command
// line.
-void cmdline_paste_str(char_u *s, int literally)
+void cmdline_paste_str(char *s, int literally)
{
int c, cv;
if (literally) {
- put_on_cmdline((char *)s, -1, true);
+ put_on_cmdline(s, -1, true);
} else {
while (*s != NUL) {
- cv = *s;
+ cv = (uint8_t)(*s);
if (cv == Ctrl_V && s[1]) {
s++;
}
- c = mb_cptr2char_adv((const char_u **)&s);
+ c = mb_cptr2char_adv((const char **)&s);
if (cv == Ctrl_V || c == ESC || c == Ctrl_C
|| c == CAR || c == NL || c == Ctrl_L
|| (c == Ctrl_BSL && *s == Ctrl_N)) {
@@ -3775,7 +3794,7 @@ static void redrawcmdprompt(void)
msg_putchar(ccline.cmdfirstc);
}
if (ccline.cmdprompt != NULL) {
- msg_puts_attr((const char *)ccline.cmdprompt, ccline.cmdattr);
+ msg_puts_attr(ccline.cmdprompt, ccline.cmdattr);
ccline.cmdindent = msg_col + (msg_row - cmdline_row) * Columns;
// do the reverse of cmd_startcol()
if (ccline.cmdfirstc != NUL) {
@@ -3950,8 +3969,8 @@ char *vim_strsave_fnameescape(const char *const fname, const int what)
{
#ifdef BACKSLASH_IN_FILENAME
# define PATH_ESC_CHARS " \t\n*?[{`%#'\"|!<"
-# define BUFFER_ESC_CHARS ((char_u *)" \t\n*?[`%#'\"|!<")
- char_u buf[sizeof(PATH_ESC_CHARS)];
+# define BUFFER_ESC_CHARS (" \t\n*?[`%#'\"|!<")
+ char buf[sizeof(PATH_ESC_CHARS)];
int j = 0;
// Don't escape '[', '{' and '!' if they are in 'isfname' and for the
@@ -3963,8 +3982,7 @@ char *vim_strsave_fnameescape(const char *const fname, const int what)
}
}
buf[j] = NUL;
- char *p = (char *)vim_strsave_escaped((const char_u *)fname,
- (const char_u *)buf);
+ char *p = vim_strsave_escaped(fname, buf);
#else
# define PATH_ESC_CHARS " \t\n*?[{`$\\%#'\"|!<"
# define SHELL_ESC_CHARS " \t\n*?[{`$\\%#'\"|!<>();&"
@@ -3993,11 +4011,11 @@ char *vim_strsave_fnameescape(const char *const fname, const int what)
/// Put a backslash before the file name in "pp", which is in allocated memory.
void escape_fname(char **pp)
{
- char_u *p = xmalloc(strlen(*pp) + 2);
+ char *p = xmalloc(strlen(*pp) + 2);
p[0] = '\\';
STRCPY(p + 1, *pp);
xfree(*pp);
- *pp = (char *)p;
+ *pp = p;
}
/// For each file name in files[num_files]:
@@ -4271,7 +4289,7 @@ char *check_cedit(void)
if (*p_cedit == NUL) {
cedit_key = -1;
} else {
- n = string_to_key((char_u *)p_cedit);
+ n = string_to_key(p_cedit);
if (vim_isprintc(n)) {
return e_invarg;
}
diff --git a/src/nvim/ex_getln.h b/src/nvim/ex_getln.h
index 916b695a35..61ac4b69c5 100644
--- a/src/nvim/ex_getln.h
+++ b/src/nvim/ex_getln.h
@@ -54,14 +54,14 @@ struct cmdline_info {
int cmdspos; ///< cursor column on screen
int cmdfirstc; ///< ':', '/', '?', '=', '>' or NUL
int cmdindent; ///< number of spaces before cmdline
- char_u *cmdprompt; ///< message in front of cmdline
+ char *cmdprompt; ///< message in front of cmdline
int cmdattr; ///< attributes for prompt
int overstrike; ///< Typing mode on the command line. Shared by
///< getcmdline() and put_on_cmdline().
expand_T *xpc; ///< struct being used for expansion, xp_pattern
///< may point into cmdbuff
int xp_context; ///< type of expansion
- char_u *xp_arg; ///< user-defined expansion arg
+ char *xp_arg; ///< user-defined expansion arg
int input_fn; ///< when true Invoked for input() function
unsigned prompt_id; ///< Prompt number, used to disable coloring on errors.
Callback highlight_callback; ///< Callback used for coloring user input.
diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c
index cae9c18309..3de5e1db52 100644
--- a/src/nvim/ex_session.c
+++ b/src/nvim/ex_session.c
@@ -38,7 +38,6 @@
#include "nvim/path.h"
#include "nvim/pos.h"
#include "nvim/runtime.h"
-#include "nvim/types.h"
#include "nvim/vim.h"
#include "nvim/window.h"
@@ -113,40 +112,43 @@ static int ses_win_rec(FILE *fd, frame_T *fr)
frame_T *frc;
int count = 0;
- if (fr->fr_layout != FR_LEAF) {
- // Find first frame that's not skipped and then create a window for
- // each following one (first frame is already there).
- frc = ses_skipframe(fr->fr_child);
- if (frc != NULL) {
- while ((frc = ses_skipframe(frc->fr_next)) != NULL) {
- // Make window as big as possible so that we have lots of room
- // to split.
- if (fprintf(fd, "%s%s",
- "wincmd _ | wincmd |\n",
- (fr->fr_layout == FR_COL ? "split\n" : "vsplit\n")) < 0) {
- return FAIL;
- }
- count++;
+ if (fr->fr_layout == FR_LEAF) {
+ return OK;
+ }
+
+ // Find first frame that's not skipped and then create a window for
+ // each following one (first frame is already there).
+ frc = ses_skipframe(fr->fr_child);
+ if (frc != NULL) {
+ while ((frc = ses_skipframe(frc->fr_next)) != NULL) {
+ // Make window as big as possible so that we have lots of room
+ // to split.
+ if (fprintf(fd, "%s%s",
+ "wincmd _ | wincmd |\n",
+ (fr->fr_layout == FR_COL ? "split\n" : "vsplit\n")) < 0) {
+ return FAIL;
}
+ count++;
}
+ }
- // Go back to the first window.
- if (count > 0 && (fprintf(fd, fr->fr_layout == FR_COL
- ? "%dwincmd k\n" : "%dwincmd h\n", count) < 0)) {
- return FAIL;
- }
+ // Go back to the first window.
+ if (count > 0 && (fprintf(fd, fr->fr_layout == FR_COL
+ ? "%dwincmd k\n" : "%dwincmd h\n", count) < 0)) {
+ return FAIL;
+ }
- // Recursively create frames/windows in each window of this column or row.
- frc = ses_skipframe(fr->fr_child);
- while (frc != NULL) {
- ses_win_rec(fd, frc);
- frc = ses_skipframe(frc->fr_next);
- // Go to next window.
- if (frc != NULL && put_line(fd, "wincmd w") == FAIL) {
- return FAIL;
- }
+ // Recursively create frames/windows in each window of this column or row.
+ frc = ses_skipframe(fr->fr_child);
+ while (frc != NULL) {
+ ses_win_rec(fd, frc);
+ frc = ses_skipframe(frc->fr_next);
+ // Go to next window.
+ if (frc != NULL && put_line(fd, "wincmd w") == FAIL) {
+ return FAIL;
}
}
+
return OK;
}
@@ -907,12 +909,14 @@ static int makeopens(FILE *fd, char *dirnow)
void ex_loadview(exarg_T *eap)
{
char *fname = get_view_file(*eap->arg);
- if (fname != NULL) {
- if (do_source(fname, false, DOSO_NONE) == FAIL) {
- semsg(_(e_notopen), fname);
- }
- xfree(fname);
+ if (fname == NULL) {
+ return;
+ }
+
+ if (do_source(fname, false, DOSO_NONE) == FAIL) {
+ semsg(_(e_notopen), fname);
}
+ xfree(fname);
}
/// ":mkexrc", ":mkvimrc", ":mkview", ":mksession".
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index d0280b3571..a0435afd65 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -143,7 +143,7 @@ typedef struct ff_visited_list_hdr {
// '**' can be expanded to several directory levels.
// Set the default maximum depth.
-#define FF_MAX_STAR_STAR_EXPAND ((char_u)30)
+#define FF_MAX_STAR_STAR_EXPAND 30
// The search context:
// ffsc_stack_ptr: the stack for the dirs to search
@@ -182,7 +182,7 @@ typedef struct ff_search_ctx_T {
# include "file_search.c.generated.h"
#endif
-static char_u e_pathtoolong[] = N_("E854: path too long for completion");
+static char e_pathtoolong[] = N_("E854: path too long for completion");
/// Initialization routine for vim_findfile().
///
@@ -302,14 +302,12 @@ void *vim_findfile_init(char *path, char *filename, char *stopdirs, int level, i
#ifdef BACKSLASH_IN_FILENAME
// "c:dir" needs "c:" to be expanded, otherwise use current dir
if (*path != NUL && path[1] == ':') {
- char_u drive[3];
+ char drive[3];
drive[0] = path[0];
drive[1] = ':';
drive[2] = NUL;
- if (vim_FullName((const char *)drive, (char *)ff_expand_buffer, MAXPATHL,
- true)
- == FAIL) {
+ if (vim_FullName(drive, ff_expand_buffer, MAXPATHL, true) == FAIL) {
goto error_return;
}
path += 2;
@@ -504,15 +502,15 @@ error_return:
}
/// @return the stopdir string. Check that ';' is not escaped.
-char_u *vim_findfile_stopdir(char *buf)
+char *vim_findfile_stopdir(char *buf)
{
- char_u *r_ptr = (char_u *)buf;
+ char *r_ptr = buf;
while (*r_ptr != NUL && *r_ptr != ';') {
if (r_ptr[0] == '\\' && r_ptr[1] == ';') {
// Overwrite the escape char,
// use strlen(r_ptr) to move the trailing '\0'.
- STRMOVE(r_ptr, (char *)r_ptr + 1);
+ STRMOVE(r_ptr, r_ptr + 1);
r_ptr++;
}
r_ptr++;
@@ -551,7 +549,7 @@ void vim_findfile_cleanup(void *ctx)
///
/// @return a pointer to an allocated file name or,
/// NULL if nothing found.
-char_u *vim_findfile(void *search_ctx_arg)
+char *vim_findfile(void *search_ctx_arg)
{
char *file_path;
char *rest_of_wildcards;
@@ -829,7 +827,7 @@ char_u *vim_findfile(void *search_ctx_arg)
verbose_leave_scroll();
}
#endif
- return (char_u *)file_path;
+ return file_path;
}
// Not found or found already, try next suffix.
@@ -1094,7 +1092,7 @@ static int ff_check_visited(ff_visited_T **visited_list, char *fname, char *wc_p
}
// New file/dir. Add it to the list of visited files/dirs.
- vp = xmalloc(sizeof(ff_visited_T) + strlen(ff_expand_buffer));
+ vp = xmalloc(offsetof(ff_visited_T, ffv_fname) + strlen(ff_expand_buffer) + 1);
if (!url) {
vp->file_id_valid = true;
@@ -1287,13 +1285,13 @@ static int ff_path_in_stoplist(char *path, int path_len, char **stopdirs_v)
/// @param rel_fname file name searching relative to
///
/// @return an allocated string for the file name. NULL for error.
-char_u *find_file_in_path(char *ptr, size_t len, int options, int first, char *rel_fname)
+char *find_file_in_path(char *ptr, size_t len, int options, int first, char *rel_fname)
{
- return (char_u *)find_file_in_path_option(ptr, len, options, first,
- (*curbuf->b_p_path == NUL
- ? (char *)p_path
- : curbuf->b_p_path),
- FINDFILE_BOTH, rel_fname, curbuf->b_p_sua);
+ return find_file_in_path_option(ptr, len, options, first,
+ (*curbuf->b_p_path == NUL
+ ? p_path
+ : curbuf->b_p_path),
+ FINDFILE_BOTH, rel_fname, curbuf->b_p_sua);
}
static char *ff_file_to_find = NULL;
@@ -1322,10 +1320,10 @@ void free_findfile(void)
/// @param rel_fname file name searching relative to
///
/// @return an allocated string for the file name. NULL for error.
-char_u *find_directory_in_path(char_u *ptr, size_t len, int options, char_u *rel_fname)
+char *find_directory_in_path(char *ptr, size_t len, int options, char *rel_fname)
{
- return (char_u *)find_file_in_path_option((char *)ptr, len, options, true, (char *)p_cdpath,
- FINDFILE_DIR, (char *)rel_fname, "");
+ return find_file_in_path_option(ptr, len, options, true, p_cdpath,
+ FINDFILE_DIR, rel_fname, "");
}
/// @param ptr file name
@@ -1446,7 +1444,7 @@ char *find_file_in_path_option(char *ptr, size_t len, int options, int first, ch
for (;;) {
if (did_findfile_init) {
- file_name = (char *)vim_findfile(fdip_search_ctx);
+ file_name = vim_findfile(fdip_search_ctx);
if (file_name != NULL) {
break;
}
@@ -1469,7 +1467,7 @@ char *find_file_in_path_option(char *ptr, size_t len, int options, int first, ch
copy_option_part(&dir, buf, MAXPATHL, " ,");
// get the stopdir string
- r_ptr = (char *)vim_findfile_stopdir(buf);
+ r_ptr = vim_findfile_stopdir(buf);
fdip_search_ctx = vim_findfile_init(buf, ff_file_to_find,
r_ptr, 100, false, find_what,
fdip_search_ctx, false, rel_fname);
@@ -1610,8 +1608,8 @@ int vim_chdirfile(char *fname, CdCause cause)
/// Change directory to "new_dir". Search 'cdpath' for relative directory names.
int vim_chdir(char *new_dir)
{
- char *dir_name = (char *)find_directory_in_path((char_u *)new_dir, strlen(new_dir),
- FNAME_MESS, (char_u *)curbuf->b_ffname);
+ char *dir_name = find_directory_in_path(new_dir, strlen(new_dir),
+ FNAME_MESS, curbuf->b_ffname);
if (dir_name == NULL) {
return -1;
}
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 0ee547d124..fbb5c4f1fa 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -105,7 +105,7 @@ enum {
// Structure to pass arguments from buf_write() to buf_write_bytes().
struct bw_info {
int bw_fd; // file descriptor
- char_u *bw_buf; // buffer with data to be written
+ char *bw_buf; // buffer with data to be written
int bw_len; // length of data
#ifdef HAS_BW_FLAGS
int bw_flags; // FIO_ flags
@@ -113,14 +113,12 @@ struct bw_info {
char_u bw_rest[CONV_RESTLEN]; // not converted bytes
int bw_restlen; // nr of bytes in bw_rest[]
int bw_first; // first write call
- char_u *bw_conv_buf; // buffer for writing converted chars
+ char *bw_conv_buf; // buffer for writing converted chars
size_t bw_conv_buflen; // size of bw_conv_buf
int bw_conv_error; // set for conversion error
linenr_T bw_conv_error_lnum; // first line with error or zero
linenr_T bw_start_lnum; // line number at start of buffer
-#ifdef HAVE_ICONV
iconv_t bw_iconv_fd; // descriptor for iconv() or -1
-#endif
};
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -248,11 +246,9 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
char *fenc_next = NULL; // next item in 'fencs' or NULL
bool advance_fenc = false;
long real_size = 0;
-#ifdef HAVE_ICONV
iconv_t iconv_fd = (iconv_t)-1; // descriptor for iconv() or -1
bool did_iconv = false; // true when iconv() failed and trying
// 'charconvert' next
-#endif
bool converted = false; // true if conversion done
bool notconverted = false; // true if conversion wanted but it wasn't possible
char conv_rest[CONV_RESTLEN];
@@ -278,7 +274,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
&& fname != NULL
&& vim_strchr(p_cpo, CPO_FNAMER) != NULL
&& !(flags & READ_DUMMY)) {
- if (set_rw_fname((char_u *)fname, (char_u *)sfname) == FAIL) {
+ if (set_rw_fname(fname, sfname) == FAIL) {
return FAIL;
}
}
@@ -779,13 +775,11 @@ retry:
}
}
-#ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
// aborted conversion with iconv(), close the descriptor
iconv_close(iconv_fd);
iconv_fd = (iconv_t)-1;
}
-#endif
if (advance_fenc) {
// Try the next entry in 'fileencodings'.
@@ -835,32 +829,24 @@ retry:
// appears not to handle this correctly. This works just like
// conversion to UTF-8 except how the resulting character is put in
// the buffer.
- fio_flags = get_fio_flags((char_u *)fenc);
+ fio_flags = get_fio_flags(fenc);
}
-#ifdef HAVE_ICONV
// Try using iconv() if we can't convert internally.
if (fio_flags == 0
&& !did_iconv) {
- iconv_fd = (iconv_t)my_iconv_open((char_u *)"utf-8", (char_u *)fenc);
+ iconv_fd = (iconv_t)my_iconv_open("utf-8", fenc);
}
-#endif
// Use the 'charconvert' expression when conversion is required
// and we can't do it internally or with iconv().
if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL
- && !read_fifo
-#ifdef HAVE_ICONV
- && iconv_fd == (iconv_t)-1
-#endif
- ) {
-#ifdef HAVE_ICONV
+ && !read_fifo && iconv_fd == (iconv_t)-1) {
did_iconv = false;
-#endif
// Skip conversion when it's already done (retry for wrong
// "fileformat").
if (tmpname == NULL) {
- tmpname = (char *)readfile_charconvert((char_u *)fname, (char_u *)fenc, &fd);
+ tmpname = readfile_charconvert(fname, fenc, &fd);
if (tmpname == NULL) {
// Conversion failed. Try another one.
advance_fenc = true;
@@ -874,11 +860,7 @@ retry:
}
}
} else {
- if (fio_flags == 0
-#ifdef HAVE_ICONV
- && iconv_fd == (iconv_t)-1
-#endif
- ) {
+ if (fio_flags == 0 && iconv_fd == (iconv_t)-1) {
// Conversion wanted but we can't.
// Try the next conversion in 'fileencodings'
advance_fenc = true;
@@ -961,12 +943,9 @@ retry:
// ucs-4 to utf-8: 4 bytes become up to 6 bytes, size must be
// multiple of 4
real_size = (int)size;
-#ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
size = size / ICONV_MULT;
- } else {
-#endif
- if (fio_flags & FIO_LATIN1) {
+ } else if (fio_flags & FIO_LATIN1) {
size = size / 2;
} else if (fio_flags & (FIO_UCS2 | FIO_UTF16)) {
size = (size * 2 / 3) & ~1;
@@ -975,9 +954,7 @@ retry:
} else if (fio_flags == FIO_UCSBOM) {
size = size / ICONV_MULT; // worst case
}
-#ifdef HAVE_ICONV
- }
-#endif
+
if (conv_restlen > 0) {
// Insert unconverted bytes from previous line.
memmove(ptr, conv_rest, (size_t)conv_restlen); // -V614
@@ -991,13 +968,11 @@ retry:
if (read_buf_lnum > from) {
size = 0;
} else {
- int n, ni;
- long tlen;
-
- tlen = 0;
+ int ni;
+ long tlen = 0;
for (;;) {
p = (char_u *)ml_get(read_buf_lnum) + read_buf_col;
- n = (int)strlen((char *)p);
+ int n = (int)strlen((char *)p);
if ((int)tlen + n + 1 > size) {
// Filled up to "size", append partial line.
// Change NL to NUL to reverse the effect done
@@ -1049,11 +1024,7 @@ retry:
// not be converted. Truncated file?
// When we did a conversion report an error.
- if (fio_flags != 0
-#ifdef HAVE_ICONV
- || iconv_fd != (iconv_t)-1
-#endif
- ) {
+ if (fio_flags != 0 || iconv_fd != (iconv_t)-1) {
if (can_retry) {
goto rewind_retry;
}
@@ -1074,23 +1045,17 @@ retry:
// character if we were converting; if we weren't,
// leave the UTF8 checking code to do it, as it
// works slightly differently.
- if (bad_char_behavior != BAD_KEEP && (fio_flags != 0
-#ifdef HAVE_ICONV
- || iconv_fd != (iconv_t)-1
-#endif
- )) { // NOLINT(whitespace/parens)
+ if (bad_char_behavior != BAD_KEEP && (fio_flags != 0 || iconv_fd != (iconv_t)-1)) {
while (conv_restlen > 0) {
*(--ptr) = (char)bad_char_behavior;
conv_restlen--;
}
}
fio_flags = 0; // don't convert this
-#ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
iconv_close(iconv_fd);
iconv_fd = (iconv_t)-1;
}
-#endif
}
}
}
@@ -1107,15 +1072,15 @@ retry:
|| (!curbuf->b_p_bomb
&& tmpname == NULL
&& (*fenc == 'u' || *fenc == NUL)))) {
- char_u *ccname;
+ char *ccname;
int blen = 0;
// no BOM detection in a short file or in binary mode
if (size < 2 || curbuf->b_p_bin) {
ccname = NULL;
} else {
- ccname = check_for_bom((char_u *)ptr, size, &blen,
- fio_flags == FIO_UCSBOM ? FIO_ALL : get_fio_flags((char_u *)fenc));
+ ccname = check_for_bom(ptr, size, &blen,
+ fio_flags == FIO_UCSBOM ? FIO_ALL : get_fio_flags(fenc));
}
if (ccname != NULL) {
// Remove BOM from the text
@@ -1137,7 +1102,7 @@ retry:
if (fenc_alloced) {
xfree(fenc);
}
- fenc = (char *)ccname;
+ fenc = ccname;
fenc_alloced = false;
}
// retry reading without getting new bytes or rewinding
@@ -1155,7 +1120,6 @@ retry:
break;
}
-#ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
// Attempt conversion of the read bytes to 'encoding' using iconv().
const char *fromp = ptr;
@@ -1175,7 +1139,7 @@ retry:
goto rewind_retry;
}
if (conv_error == 0) {
- conv_error = readfile_linenr(linecnt, (char_u *)ptr, (char_u *)top);
+ conv_error = readfile_linenr(linecnt, ptr, top);
}
// Deal with a bad byte and continue with the next.
@@ -1193,7 +1157,7 @@ retry:
if (from_size > 0) {
// Some remaining characters, keep them for the next
// round.
- memmove(conv_rest, (char_u *)fromp, from_size);
+ memmove(conv_rest, fromp, from_size);
conv_restlen = (int)from_size;
}
@@ -1202,7 +1166,6 @@ retry:
memmove(line_start, buffer, (size_t)linerest);
size = (top - ptr);
}
-#endif
if (fio_flags != 0) {
unsigned int u8c;
@@ -1287,7 +1250,7 @@ retry:
goto rewind_retry;
}
if (conv_error == 0) {
- conv_error = readfile_linenr(linecnt, (char_u *)ptr, p);
+ conv_error = readfile_linenr(linecnt, ptr, (char *)p);
}
if (bad_char_behavior == BAD_DROP) {
continue;
@@ -1315,7 +1278,7 @@ retry:
goto rewind_retry;
}
if (conv_error == 0) {
- conv_error = readfile_linenr(linecnt, (char_u *)ptr, p);
+ conv_error = readfile_linenr(linecnt, ptr, (char *)p);
}
if (bad_char_behavior == BAD_DROP) {
continue;
@@ -1356,7 +1319,7 @@ retry:
goto rewind_retry;
}
if (conv_error == 0) {
- conv_error = readfile_linenr(linecnt, (char_u *)ptr, p);
+ conv_error = readfile_linenr(linecnt, ptr, (char *)p);
}
if (bad_char_behavior == BAD_DROP) {
continue;
@@ -1394,7 +1357,7 @@ retry:
// an incomplete character at the end though, the next
// read() will get the next bytes, we'll check it
// then.
- l = utf_ptr2len_len(p, todo);
+ l = utf_ptr2len_len((char *)p, todo);
if (l > todo && !incomplete_tail) {
// Avoid retrying with a different encoding when
// a truncated file is more likely, or attempting
@@ -1420,15 +1383,15 @@ retry:
if (can_retry && !incomplete_tail) {
break;
}
-#ifdef HAVE_ICONV
+
// When we did a conversion report an error.
if (iconv_fd != (iconv_t)-1 && conv_error == 0) {
- conv_error = readfile_linenr(linecnt, (char_u *)ptr, p);
+ conv_error = readfile_linenr(linecnt, ptr, (char *)p);
}
-#endif
+
// Remember the first linenr with an illegal byte
if (conv_error == 0 && illegal_byte == 0) {
- illegal_byte = readfile_linenr(linecnt, (char_u *)ptr, p);
+ illegal_byte = readfile_linenr(linecnt, ptr, (char *)p);
}
// Drop, keep or replace the bad byte.
@@ -1448,17 +1411,13 @@ retry:
// Detected a UTF-8 error.
rewind_retry:
// Retry reading with another conversion.
-#ifdef HAVE_ICONV
if (*p_ccv != NUL && iconv_fd != (iconv_t)-1) {
// iconv() failed, try 'charconvert'
did_iconv = true;
} else {
-#endif
- // use next item from 'fileencodings'
- advance_fenc = true;
-#ifdef HAVE_ICONV
- }
-#endif
+ // use next item from 'fileencodings'
+ advance_fenc = true;
+ }
file_rewind = true;
goto retry;
}
@@ -1554,7 +1513,7 @@ rewind_retry:
break;
}
if (read_undo_file) {
- sha256_update(&sha_ctx, (char_u *)line_start, (size_t)len);
+ sha256_update(&sha_ctx, (uint8_t *)line_start, (size_t)len);
}
lnum++;
if (--read_count == 0) {
@@ -1610,7 +1569,7 @@ rewind_retry:
break;
}
if (read_undo_file) {
- sha256_update(&sha_ctx, (char_u *)line_start, (size_t)len);
+ sha256_update(&sha_ctx, (uint8_t *)line_start, (size_t)len);
}
lnum++;
if (--read_count == 0) {
@@ -1667,7 +1626,7 @@ failed:
error = true;
} else {
if (read_undo_file) {
- sha256_update(&sha_ctx, (char_u *)line_start, (size_t)len);
+ sha256_update(&sha_ctx, (uint8_t *)line_start, (size_t)len);
}
read_no_eol_lnum = ++lnum;
}
@@ -1683,11 +1642,9 @@ failed:
if (fenc_alloced) {
xfree(fenc);
}
-#ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
iconv_close(iconv_fd);
}
-#endif
if (!read_buffer && !read_stdin) {
close(fd); // errors are ignored
@@ -1887,7 +1844,7 @@ failed:
char_u hash[UNDO_HASH_SIZE];
sha256_finish(&sha_ctx, hash);
- u_read_undo(NULL, hash, (char_u *)fname);
+ u_read_undo(NULL, hash, fname);
}
if (!read_stdin && !read_fifo && (!read_buffer || sfname != NULL)) {
@@ -1958,9 +1915,9 @@ bool is_dev_fd_file(char *fname)
/// @param linecnt line count before reading more bytes
/// @param p start of more bytes read
/// @param endp end of more bytes read
-static linenr_T readfile_linenr(linenr_T linecnt, char_u *p, const char_u *endp)
+static linenr_T readfile_linenr(linenr_T linecnt, char *p, const char *endp)
{
- char_u *s;
+ char *s;
linenr_T lnum;
lnum = curbuf->b_ml.ml_line_count - linecnt + 1;
@@ -2040,7 +1997,7 @@ static char *next_fenc(char **pp, bool *alloced)
*pp = NULL;
return "";
}
- p = vim_strchr((*pp), ',');
+ p = vim_strchr(*pp, ',');
if (p == NULL) {
r = enc_canonize(*pp);
*pp += strlen(*pp);
@@ -2065,22 +2022,22 @@ static char *next_fenc(char **pp, bool *alloced)
///
/// @return name of the resulting converted file (the caller should delete it after reading it).
/// Returns NULL if the conversion failed ("*fdp" is not set) .
-static char_u *readfile_charconvert(char_u *fname, char_u *fenc, int *fdp)
+static char *readfile_charconvert(char *fname, char *fenc, int *fdp)
{
- char_u *tmpname;
+ char *tmpname;
char *errmsg = NULL;
- tmpname = (char_u *)vim_tempname();
+ tmpname = vim_tempname();
if (tmpname == NULL) {
errmsg = _("Can't find temp file for conversion");
} else {
close(*fdp); // close the input file, ignore errors
*fdp = -1;
- if (eval_charconvert((char *)fenc, "utf-8",
- (char *)fname, (char *)tmpname) == FAIL) {
+ if (eval_charconvert(fenc, "utf-8",
+ fname, tmpname) == FAIL) {
errmsg = _("Conversion with 'charconvert' failed");
}
- if (errmsg == NULL && (*fdp = os_open((char *)tmpname, O_RDONLY, 0)) < 0) {
+ if (errmsg == NULL && (*fdp = os_open(tmpname, O_RDONLY, 0)) < 0) {
errmsg = _("can't read output of 'charconvert'");
}
}
@@ -2090,14 +2047,14 @@ static char_u *readfile_charconvert(char_u *fname, char_u *fenc, int *fdp)
// another type of conversion might still work.
msg(errmsg);
if (tmpname != NULL) {
- os_remove((char *)tmpname); // delete converted file
+ os_remove(tmpname); // delete converted file
XFREE_CLEAR(tmpname);
}
}
// If the input file is closed, open it (caller should check for error).
if (*fdp < 0) {
- *fdp = os_open((char *)fname, O_RDONLY, 0);
+ *fdp = os_open(fname, O_RDONLY, 0);
}
return tmpname;
@@ -2167,7 +2124,6 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
bool errmsg_allocated = false;
char *buffer;
char smallbuf[SMBUFSIZE];
- char *backup_ext;
int bufsize;
long perm; // file permissions
int retval = OK;
@@ -2233,9 +2189,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
write_info.bw_conv_error = false;
write_info.bw_conv_error_lnum = 0;
write_info.bw_restlen = 0;
-#ifdef HAVE_ICONV
write_info.bw_iconv_fd = (iconv_t)-1;
-#endif
// After writing a file changedtick changes but we don't want to display
// the line.
@@ -2254,7 +2208,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
&& !filtering
&& (!append || vim_strchr(p_cpo, CPO_FNAMEAPP) != NULL)
&& vim_strchr(p_cpo, CPO_FNAMEW) != NULL) {
- if (set_rw_fname((char_u *)fname, (char_u *)sfname) == FAIL) {
+ if (set_rw_fname(fname, sfname) == FAIL) {
return FAIL;
}
buf = curbuf; // just in case autocmds made "buf" invalid
@@ -2473,7 +2427,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
if (!filtering) {
filemess(buf,
#ifndef UNIX
- (char_u *)sfname,
+ sfname,
#else
fname,
#endif
@@ -2517,7 +2471,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
}
#else // win32
// Check for a writable device name.
- c = fname == NULL ? NODE_OTHER : os_nodetype((char *)fname);
+ c = fname == NULL ? NODE_OTHER : os_nodetype(fname);
if (c == NODE_OTHER) {
SET_ERRMSG_NUM("E503", _("is not a file or writable device"));
goto fail;
@@ -2535,7 +2489,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
goto fail;
}
if (overwriting) {
- os_fileinfo((char *)fname, &file_info_old);
+ os_fileinfo(fname, &file_info_old);
}
}
#endif // !UNIX
@@ -2566,13 +2520,13 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
#ifdef HAVE_ACL
// For systems that support ACL: get the ACL from the original file.
if (!newfile) {
- acl = os_get_acl((char_u *)fname);
+ acl = os_get_acl(fname);
}
#endif
// If 'backupskip' is not empty, don't make a backup for some files.
dobackup = (p_wb || p_bk || *p_pm != NUL);
- if (dobackup && *p_bsk != NUL && match_file_list(p_bsk, (char_u *)sfname, (char_u *)ffname)) {
+ if (dobackup && *p_bsk != NUL && match_file_list(p_bsk, sfname, ffname)) {
dobackup = false;
}
@@ -2598,8 +2552,6 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
if ((bkc & BKC_YES) || append) { // "yes"
backup_copy = true;
} else if ((bkc & BKC_AUTO)) { // "auto"
- int i;
-
// Don't rename the file when:
// - it's a hard link
// - it's a symbolic link
@@ -2614,7 +2566,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
// First find a file name that doesn't exist yet (use some
// arbitrary numbers).
STRCPY(IObuff, fname);
- for (i = 4913;; i += 123) {
+ for (int i = 4913;; i += 123) {
char *tail = path_tail(IObuff);
size_t size = (size_t)(tail - IObuff);
snprintf(tail, IOSIZE - size, "%d", i);
@@ -2667,18 +2619,10 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
}
// make sure we have a valid backup extension to use
- if (*p_bex == NUL) {
- backup_ext = ".bak";
- } else {
- backup_ext = p_bex;
- }
+ char *backup_ext = *p_bex == NUL ? ".bak" : p_bex;
if (backup_copy) {
- char *wp;
int some_error = false;
- char *dirp;
- char *rootname;
- char *p;
// Try to make the backup in each directory in the 'bdir' option.
//
@@ -2690,11 +2634,11 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
//
// For these reasons, the existing writable file must be truncated
// and reused. Creation of a backup COPY will be attempted.
- dirp = p_bdir;
+ char *dirp = p_bdir;
while (*dirp) {
// Isolate one directory name, using an entry in 'bdir'.
size_t dir_len = copy_option_part(&dirp, IObuff, IOSIZE, ",");
- p = IObuff + dir_len;
+ char *p = IObuff + dir_len;
bool trailing_pathseps = after_pathsep(IObuff, p) && p[-1] == p[-2];
if (trailing_pathseps) {
IObuff[dir_len - 2] = NUL;
@@ -2717,7 +2661,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
}
}
- rootname = get_file_in_dir(fname, IObuff);
+ char *rootname = get_file_in_dir(fname, IObuff);
if (rootname == NULL) {
some_error = true; // out of memory
goto nobackup;
@@ -2753,7 +2697,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
// delete an existing one, and try to use another name instead.
// Change one character, just before the extension.
//
- wp = backup + strlen(backup) - 1 - strlen(backup_ext);
+ char *wp = backup + strlen(backup) - 1 - strlen(backup_ext);
if (wp < backup) { // empty file name ???
wp = backup;
}
@@ -2806,7 +2750,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
(double)file_info_old.stat.st_mtim.tv_sec);
#endif
#ifdef HAVE_ACL
- os_set_acl((char_u *)backup, acl);
+ os_set_acl(backup, acl);
#endif
SET_ERRMSG(NULL);
break;
@@ -2824,10 +2768,6 @@ nobackup:
}
SET_ERRMSG(NULL);
} else {
- char *dirp;
- char *p;
- char *rootname;
-
// Make a backup by renaming the original file.
// If 'cpoptions' includes the "W" flag, we don't want to
@@ -2841,11 +2781,11 @@ nobackup:
// Form the backup file name - change path/fo.o.h to
// path/fo.o.h.bak Try all directories in 'backupdir', first one
// that works is used.
- dirp = p_bdir;
+ char *dirp = p_bdir;
while (*dirp) {
// Isolate one directory name and make the backup file name.
size_t dir_len = copy_option_part(&dirp, IObuff, IOSIZE, ",");
- p = IObuff + dir_len;
+ char *p = IObuff + dir_len;
bool trailing_pathseps = after_pathsep(IObuff, p) && p[-1] == p[-2];
if (trailing_pathseps) {
IObuff[dir_len - 2] = NUL;
@@ -2869,7 +2809,7 @@ nobackup:
}
if (backup == NULL) {
- rootname = get_file_in_dir(fname, IObuff);
+ char *rootname = get_file_in_dir(fname, IObuff);
if (rootname == NULL) {
backup = NULL;
} else {
@@ -2980,7 +2920,7 @@ nobackup:
// Latin1 to Unicode conversion. This is handled in buf_write_bytes().
// Prepare the flags for it and allocate bw_conv_buf when needed.
if (converted) {
- wb_flags = get_fio_flags((char_u *)fenc);
+ wb_flags = get_fio_flags(fenc);
if (wb_flags & (FIO_UCS2 | FIO_UCS4 | FIO_UTF16 | FIO_UTF8)) {
// Need to allocate a buffer to translate into.
if (wb_flags & (FIO_UCS2 | FIO_UTF16 | FIO_UTF8)) {
@@ -2996,10 +2936,9 @@ nobackup:
}
if (converted && wb_flags == 0) {
-#ifdef HAVE_ICONV
// Use iconv() conversion when conversion is needed and it's not done
// internally.
- write_info.bw_iconv_fd = (iconv_t)my_iconv_open((char_u *)fenc, (char_u *)"utf-8");
+ write_info.bw_iconv_fd = (iconv_t)my_iconv_open(fenc, "utf-8");
if (write_info.bw_iconv_fd != (iconv_t)-1) {
// We're going to use iconv(), allocate a buffer to convert in.
write_info.bw_conv_buflen = (size_t)bufsize * ICONV_MULT;
@@ -3009,28 +2948,21 @@ nobackup:
}
write_info.bw_first = true;
} else {
-#endif
-
- // When the file needs to be converted with 'charconvert' after
- // writing, write to a temp file instead and let the conversion
- // overwrite the original file.
- if (*p_ccv != NUL) {
- wfname = vim_tempname();
- if (wfname == NULL) { // Can't write without a tempfile!
- SET_ERRMSG(_("E214: Can't find temp file for writing"));
- goto restore_backup;
+ // When the file needs to be converted with 'charconvert' after
+ // writing, write to a temp file instead and let the conversion
+ // overwrite the original file.
+ if (*p_ccv != NUL) {
+ wfname = vim_tempname();
+ if (wfname == NULL) { // Can't write without a tempfile!
+ SET_ERRMSG(_("E214: Can't find temp file for writing"));
+ goto restore_backup;
+ }
}
}
}
-#ifdef HAVE_ICONV
-}
-#endif
-
if (converted && wb_flags == 0
-#ifdef HAVE_ICONV
&& write_info.bw_iconv_fd == (iconv_t)-1
-#endif
&& wfname == fname) {
if (!forceit) {
SET_ERRMSG(_("E213: Cannot convert (add ! to write without conversion)"));
@@ -3151,7 +3083,7 @@ restore_backup:
}
SET_ERRMSG(NULL);
- write_info.bw_buf = (char_u *)buffer;
+ write_info.bw_buf = buffer;
nchars = 0;
// use "++bin", "++nobin" or 'binary'
@@ -3164,7 +3096,7 @@ restore_backup:
// Skip the BOM when appending and the file already existed, the BOM
// only makes sense at the start of the file.
if (buf->b_p_bomb && !write_bin && (!append || perm < 0)) {
- write_info.bw_len = make_bom((char_u *)buffer, (char_u *)fenc);
+ write_info.bw_len = make_bom((char_u *)buffer, fenc);
if (write_info.bw_len > 0) {
// don't convert
write_info.bw_flags = FIO_NOCONVERT | wb_flags;
@@ -3196,7 +3128,7 @@ restore_backup:
// Keep it fast!
ptr = ml_get_buf(buf, lnum, false) - 1;
if (write_undo_file) {
- sha256_update(&sha_ctx, (char_u *)ptr + 1, (uint32_t)(strlen(ptr + 1) + 1));
+ sha256_update(&sha_ctx, (uint8_t *)ptr + 1, (uint32_t)(strlen(ptr + 1) + 1));
}
while ((c = *++ptr) != NUL) {
if (c == NL) {
@@ -3342,7 +3274,7 @@ restore_backup:
// Probably need to set the ACL before changing the user (can't set the
// ACL on a file the user doesn't own).
if (!backup_copy) {
- os_set_acl((char_u *)wfname, acl);
+ os_set_acl(wfname, acl);
}
#endif
@@ -3551,12 +3483,10 @@ nofail:
}
xfree(fenc_tofree);
xfree(write_info.bw_conv_buf);
-#ifdef HAVE_ICONV
if (write_info.bw_iconv_fd != (iconv_t)-1) {
iconv_close(write_info.bw_iconv_fd);
write_info.bw_iconv_fd = (iconv_t)-1;
}
-#endif
#ifdef HAVE_ACL
os_free_acl(acl);
#endif
@@ -3605,10 +3535,10 @@ nofail:
// When writing the whole file and 'undofile' is set, also write the undo
// file.
if (retval == OK && write_undo_file) {
- char hash[UNDO_HASH_SIZE];
+ uint8_t hash[UNDO_HASH_SIZE];
- sha256_finish(&sha_ctx, (char_u *)hash);
- u_write_undo(NULL, false, buf, (char_u *)hash);
+ sha256_finish(&sha_ctx, hash);
+ u_write_undo(NULL, false, buf, hash);
}
if (!should_abort(retval)) {
@@ -3652,7 +3582,7 @@ nofail:
/// Set the name of the current buffer. Use when the buffer doesn't have a
/// name and a ":r" or ":w" command with a file name is used.
-static int set_rw_fname(char_u *fname, char_u *sfname)
+static int set_rw_fname(char *fname, char *sfname)
{
buf_T *buf = curbuf;
@@ -3670,7 +3600,7 @@ static int set_rw_fname(char_u *fname, char_u *sfname)
return FAIL;
}
- if (setfname(curbuf, (char *)fname, (char *)sfname, false) == OK) {
+ if (setfname(curbuf, fname, sfname, false) == OK) {
curbuf->b_flags |= BF_NOTEDITED;
}
@@ -3743,9 +3673,7 @@ static bool msg_add_fileformat(int eol_type)
/// Append line and character count to IObuff.
void msg_add_lines(int insert_space, long lnum, off_T nchars)
{
- char *p;
-
- p = IObuff + strlen(IObuff);
+ char *p = IObuff + strlen(IObuff);
if (insert_space) {
*p++ = ' ';
@@ -3801,7 +3729,7 @@ static bool time_differs(const FileInfo *file_info, long mtime, long mtime_ns) F
|| file_info->stat.st_mtim.tv_sec - mtime > 1
|| mtime - file_info->stat.st_mtim.tv_sec > 1;
#else
- || (long)file_info->stat.st_mtim.tv_sec != mtime;
+ || file_info->stat.st_mtim.tv_sec != mtime;
#endif
}
@@ -3811,48 +3739,37 @@ static bool time_differs(const FileInfo *file_info, long mtime, long mtime_ns) F
/// @return FAIL for failure, OK otherwise.
static int buf_write_bytes(struct bw_info *ip)
{
- int wlen;
- char_u *buf = ip->bw_buf; // data to write
- int len = ip->bw_len; // length of data
+ char *buf = ip->bw_buf; // data to write
+ int len = ip->bw_len; // length of data
#ifdef HAS_BW_FLAGS
- int flags = ip->bw_flags; // extra flags
+ int flags = ip->bw_flags; // extra flags
#endif
// Skip conversion when writing the BOM.
if (!(flags & FIO_NOCONVERT)) {
- char_u *p;
- unsigned c;
- int n;
-
if (flags & FIO_UTF8) {
// Convert latin1 in the buffer to UTF-8 in the file.
- p = ip->bw_conv_buf; // translate to buffer
- for (wlen = 0; wlen < len; wlen++) {
- p += utf_char2bytes(buf[wlen], (char *)p);
+ char *p = ip->bw_conv_buf; // translate to buffer
+ for (int wlen = 0; wlen < len; wlen++) {
+ p += utf_char2bytes((uint8_t)buf[wlen], p);
}
buf = ip->bw_conv_buf;
len = (int)(p - ip->bw_conv_buf);
} else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1)) {
+ unsigned c;
+ int n = 0;
// Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or
// Latin1 chars in the file.
- if (flags & FIO_LATIN1) {
- p = buf; // translate in-place (can only get shorter)
- } else {
- p = ip->bw_conv_buf; // translate to buffer
- }
- for (wlen = 0; wlen < len; wlen += n) {
+ // translate in-place (can only get shorter) or to buffer
+ char *p = flags & FIO_LATIN1 ? buf : ip->bw_conv_buf;
+ for (int wlen = 0; wlen < len; wlen += n) {
if (wlen == 0 && ip->bw_restlen != 0) {
- int l;
-
// Use remainder of previous call. Append the start of
// buf[] to get a full sequence. Might still be too
// short!
- l = CONV_RESTLEN - ip->bw_restlen;
- if (l > len) {
- l = len;
- }
+ int l = MIN(len, CONV_RESTLEN - ip->bw_restlen);
memmove(ip->bw_rest + ip->bw_restlen, buf, (size_t)l);
- n = utf_ptr2len_len(ip->bw_rest, ip->bw_restlen + l);
+ n = utf_ptr2len_len((char *)ip->bw_rest, ip->bw_restlen + l);
if (n > ip->bw_restlen + len) {
// We have an incomplete byte sequence at the end to
// be written. We can't convert it without the
@@ -3892,9 +3809,9 @@ static int buf_write_bytes(struct bw_info *ip)
break;
}
if (n > 1) {
- c = (unsigned)utf_ptr2char((char *)buf + wlen);
+ c = (unsigned)utf_ptr2char(buf + wlen);
} else {
- c = buf[wlen];
+ c = (uint8_t)buf[wlen];
}
}
@@ -3914,32 +3831,28 @@ static int buf_write_bytes(struct bw_info *ip)
}
}
-#ifdef HAVE_ICONV
if (ip->bw_iconv_fd != (iconv_t)-1) {
const char *from;
size_t fromlen;
- char *to;
size_t tolen;
// Convert with iconv().
if (ip->bw_restlen > 0) {
- char *fp;
-
// Need to concatenate the remainder of the previous call and
// the bytes of the current call. Use the end of the
// conversion buffer for this.
fromlen = (size_t)len + (size_t)ip->bw_restlen;
- fp = (char *)ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
+ char *fp = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
memmove(fp, ip->bw_rest, (size_t)ip->bw_restlen);
memmove(fp + ip->bw_restlen, buf, (size_t)len);
from = fp;
tolen = ip->bw_conv_buflen - fromlen;
} else {
- from = (const char *)buf;
+ from = buf;
fromlen = (size_t)len;
tolen = ip->bw_conv_buflen;
}
- to = (char *)ip->bw_conv_buf;
+ char *to = ip->bw_conv_buf;
if (ip->bw_first) {
size_t save_len = tolen;
@@ -3950,7 +3863,7 @@ static int buf_write_bytes(struct bw_info *ip)
// There is a bug in iconv() on Linux (which appears to be
// wide-spread) which sets "to" to NULL and messes up "tolen".
if (to == NULL) {
- to = (char *)ip->bw_conv_buf;
+ to = ip->bw_conv_buf;
tolen = save_len;
}
ip->bw_first = false;
@@ -3971,16 +3884,15 @@ static int buf_write_bytes(struct bw_info *ip)
ip->bw_restlen = (int)fromlen;
buf = ip->bw_conv_buf;
- len = (int)((char_u *)to - ip->bw_conv_buf);
+ len = (int)(to - ip->bw_conv_buf);
}
-#endif
}
if (ip->bw_fd < 0) {
// Only checking conversion, which is OK if we get here.
return OK;
}
- wlen = (int)write_eintr(ip->bw_fd, buf, (size_t)len);
+ int wlen = (int)write_eintr(ip->bw_fd, buf, (size_t)len);
return (wlen < len) ? FAIL : OK;
}
@@ -3991,11 +3903,10 @@ static int buf_write_bytes(struct bw_info *ip)
/// @param flags FIO_ flags that specify which encoding to use
///
/// @return true for an error, false when it's OK.
-static bool ucs2bytes(unsigned c, char_u **pp, int flags) FUNC_ATTR_NONNULL_ALL
+static bool ucs2bytes(unsigned c, char **pp, int flags) FUNC_ATTR_NONNULL_ALL
{
- char_u *p = *pp;
+ char_u *p = (char_u *)(*pp);
bool error = false;
- int cc;
if (flags & FIO_UCS4) {
if (flags & FIO_ENDIAN_L) {
@@ -4018,7 +3929,7 @@ static bool ucs2bytes(unsigned c, char_u **pp, int flags) FUNC_ATTR_NONNULL_ALL
if (c >= 0x100000) {
error = true;
}
- cc = (int)(((c >> 10) & 0x3ff) + 0xd800);
+ int cc = (int)(((c >> 10) & 0x3ff) + 0xd800);
if (flags & FIO_ENDIAN_L) {
*p++ = (uint8_t)cc;
*p++ = (uint8_t)(cc >> 8);
@@ -4047,7 +3958,7 @@ static bool ucs2bytes(unsigned c, char_u **pp, int flags) FUNC_ATTR_NONNULL_ALL
}
}
- *pp = p;
+ *pp = (char *)p;
return error;
}
@@ -4061,7 +3972,6 @@ static bool need_conversion(const char *fenc)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
int same_encoding;
- int enc_flags;
int fenc_flags;
if (*fenc == NUL || strcmp(p_enc, fenc) == 0) {
@@ -4070,8 +3980,8 @@ static bool need_conversion(const char *fenc)
} else {
// Ignore difference between "ansi" and "latin1", "ucs-4" and
// "ucs-4be", etc.
- enc_flags = get_fio_flags((char_u *)p_enc);
- fenc_flags = get_fio_flags((char_u *)fenc);
+ int enc_flags = get_fio_flags(p_enc);
+ fenc_flags = get_fio_flags(fenc);
same_encoding = (enc_flags != 0 && fenc_flags == enc_flags);
}
if (same_encoding) {
@@ -4089,14 +3999,12 @@ static bool need_conversion(const char *fenc)
/// use 'encoding'.
///
/// @param name string to check for encoding
-static int get_fio_flags(const char_u *name)
+static int get_fio_flags(const char *name)
{
- int prop;
-
if (*name == NUL) {
- name = (char_u *)p_enc;
+ name = p_enc;
}
- prop = enc_canon_props((char *)name);
+ int prop = enc_canon_props(name);
if (prop & ENC_UNICODE) {
if (prop & ENC_2BYTE) {
if (prop & ENC_ENDIAN_L) {
@@ -4130,8 +4038,9 @@ static int get_fio_flags(const char_u *name)
///
/// @return the name of the encoding and set "*lenp" to the length or,
/// NULL when no BOM found.
-static char_u *check_for_bom(const char_u *p, long size, int *lenp, int flags)
+static char *check_for_bom(const char *p_in, long size, int *lenp, int flags)
{
+ const uint8_t *p = (const uint8_t *)p_in;
char *name = NULL;
int len = 2;
@@ -4167,18 +4076,15 @@ static char_u *check_for_bom(const char_u *p, long size, int *lenp, int flags)
}
*lenp = len;
- return (char_u *)name;
+ return name;
}
/// Generate a BOM in "buf[4]" for encoding "name".
///
/// @return the length of the BOM (zero when no BOM).
-static int make_bom(char_u *buf, char_u *name)
+static int make_bom(char_u *buf, char *name)
{
- int flags;
- char_u *p;
-
- flags = get_fio_flags(name);
+ int flags = get_fio_flags(name);
// Can't put a BOM in a non-Unicode file.
if (flags == FIO_LATIN1 || flags == 0) {
@@ -4191,9 +4097,9 @@ static int make_bom(char_u *buf, char_u *name)
buf[2] = 0xbf;
return 3;
}
- p = buf;
+ char *p = (char *)buf;
(void)ucs2bytes(0xfeff, &p, flags);
- return (int)(p - buf);
+ return (int)((char_u *)p - buf);
}
/// Shorten filename of a buffer.
@@ -4205,20 +4111,18 @@ static int make_bom(char_u *buf, char_u *name)
///
/// For buffers that have buftype "nofile" or "scratch": never change the file
/// name.
-void shorten_buf_fname(buf_T *buf, char_u *dirname, int force)
+void shorten_buf_fname(buf_T *buf, char *dirname, int force)
{
- char *p;
-
if (buf->b_fname != NULL
&& !bt_nofilename(buf)
&& !path_with_url(buf->b_fname)
&& (force
|| buf->b_sfname == NULL
- || path_is_absolute((char_u *)buf->b_sfname))) {
+ || path_is_absolute(buf->b_sfname))) {
if (buf->b_sfname != buf->b_ffname) {
XFREE_CLEAR(buf->b_sfname);
}
- p = path_shorten_fname(buf->b_ffname, (char *)dirname);
+ char *p = path_shorten_fname(buf->b_ffname, dirname);
if (p != NULL) {
buf->b_sfname = xstrdup(p);
buf->b_fname = buf->b_sfname;
@@ -4232,11 +4136,11 @@ void shorten_buf_fname(buf_T *buf, char_u *dirname, int force)
/// Shorten filenames for all buffers.
void shorten_fnames(int force)
{
- char_u dirname[MAXPATHL];
+ char dirname[MAXPATHL];
- os_dirname((char *)dirname, MAXPATHL);
+ os_dirname(dirname, MAXPATHL);
FOR_ALL_BUFFERS(buf) {
- shorten_buf_fname(buf, dirname, force);
+ shorten_buf_fname(buf, (char *)dirname, force);
// Always make the swap file name a full path, a "nofile" buffer may
// also have a swap file.
@@ -4515,10 +4419,7 @@ int vim_rename(const char *from, const char *to)
{
int fd_in;
int fd_out;
- int n;
char *errmsg = NULL;
- char *buffer;
- long perm;
#ifdef HAVE_ACL
vim_acl_T acl; // ACL from original file
#endif
@@ -4552,7 +4453,7 @@ int vim_rename(const char *from, const char *to)
}
if (use_tmp_file) {
- char_u tempname[MAXPATHL + 1];
+ char tempname[MAXPATHL + 1];
// Find a name that doesn't exist and is in the same directory.
// Rename "from" to "tempname" and then rename "tempname" to "to".
@@ -4560,18 +4461,18 @@ int vim_rename(const char *from, const char *to)
return -1;
}
STRCPY(tempname, from);
- for (n = 123; n < 99999; n++) {
- char *tail = path_tail((char *)tempname);
- snprintf(tail, (size_t)((MAXPATHL + 1) - (tail - (char *)tempname - 1)), "%d", n);
+ for (int n = 123; n < 99999; n++) {
+ char *tail = path_tail(tempname);
+ snprintf(tail, (size_t)((MAXPATHL + 1) - (tail - tempname - 1)), "%d", n);
- if (!os_path_exists((char *)tempname)) {
- if (os_rename((char_u *)from, tempname) == OK) {
- if (os_rename(tempname, (char_u *)to) == OK) {
+ if (!os_path_exists(tempname)) {
+ if (os_rename(from, tempname) == OK) {
+ if (os_rename(tempname, to) == OK) {
return 0;
}
// Strange, the second step failed. Try moving the
// file back and return failure.
- (void)os_rename(tempname, (char_u *)from);
+ (void)os_rename(tempname, from);
return -1;
}
// If it fails for one temp name it will most likely fail
@@ -4589,15 +4490,15 @@ int vim_rename(const char *from, const char *to)
os_remove((char *)to);
// First try a normal rename, return if it works.
- if (os_rename((char_u *)from, (char_u *)to) == OK) {
+ if (os_rename(from, to) == OK) {
return 0;
}
// Rename() failed, try copying the file.
- perm = os_getperm(from);
+ long perm = os_getperm(from);
#ifdef HAVE_ACL
// For systems that support ACL: get the ACL from the original file.
- acl = os_get_acl((char_u *)from);
+ acl = os_get_acl(from);
#endif
fd_in = os_open((char *)from, O_RDONLY, 0);
if (fd_in < 0) {
@@ -4620,7 +4521,7 @@ int vim_rename(const char *from, const char *to)
// Avoid xmalloc() here as vim_rename() is called by buf_write() when nvim
// is `preserve_exit()`ing.
- buffer = try_malloc(BUFSIZE);
+ char *buffer = try_malloc(BUFSIZE);
if (buffer == NULL) {
close(fd_out);
close(fd_in);
@@ -4630,6 +4531,7 @@ int vim_rename(const char *from, const char *to)
return -1;
}
+ int n;
while ((n = (int)read_eintr(fd_in, buffer, BUFSIZE)) > 0) {
if (write_eintr(fd_out, buffer, (size_t)n) != n) {
errmsg = _("E208: Error writing to \"%s\"");
@@ -4647,10 +4549,10 @@ int vim_rename(const char *from, const char *to)
to = from;
}
#ifndef UNIX // For Unix os_open() already set the permission.
- os_setperm((const char *)to, perm);
+ os_setperm(to, perm);
#endif
#ifdef HAVE_ACL
- os_set_acl((char_u *)to, acl);
+ os_set_acl(to, acl);
os_free_acl(acl);
#endif
if (errmsg != NULL) {
@@ -4673,8 +4575,6 @@ static int already_warned = false;
/// @return true if some message was written (screen should be redrawn and cursor positioned).
int check_timestamps(int focus)
{
- int didit = 0;
-
// Don't check timestamps while system() or another low-level function may
// cause us to lose and gain focus.
if (no_check_timestamps > 0) {
@@ -4689,6 +4589,8 @@ int check_timestamps(int focus)
return false;
}
+ int didit = 0;
+
if (!stuff_empty() || global_busy || !typebuf_typed()
|| autocmd_busy || curbuf->b_ro_locked > 0
|| allbuf_lock > 0) {
@@ -4732,13 +4634,11 @@ static int move_lines(buf_T *frombuf, buf_T *tobuf)
{
buf_T *tbuf = curbuf;
int retval = OK;
- linenr_T lnum;
- char *p;
// Copy the lines in "frombuf" to "tobuf".
curbuf = tobuf;
- for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; lnum++) {
- p = xstrdup(ml_get_buf(frombuf, lnum, false));
+ for (linenr_T lnum = 1; lnum <= frombuf->b_ml.ml_line_count; lnum++) {
+ char *p = xstrdup(ml_get_buf(frombuf, lnum, false));
if (ml_append(lnum - 1, p, 0, false) == FAIL) {
xfree(p);
retval = FAIL;
@@ -4750,7 +4650,7 @@ static int move_lines(buf_T *frombuf, buf_T *tobuf)
// Delete all the lines in "frombuf".
if (retval != FAIL) {
curbuf = frombuf;
- for (lnum = curbuf->b_ml.ml_line_count; lnum > 0; lnum--) {
+ for (linenr_T lnum = curbuf->b_ml.ml_line_count; lnum > 0; lnum--) {
if (ml_delete(lnum, false) == FAIL) {
// Oops! We could try putting back the saved lines, but that
// might fail again...
@@ -4774,7 +4674,6 @@ int buf_check_timestamp(buf_T *buf)
FUNC_ATTR_NONNULL_ALL
{
int retval = 0;
- char *path;
char *mesg = NULL;
char *mesg2 = "";
bool helpmesg = false;
@@ -4789,8 +4688,6 @@ int buf_check_timestamp(buf_T *buf)
uint64_t orig_size = buf->b_orig_size;
int orig_mode = buf->b_orig_mode;
static bool busy = false;
- char *s;
- char *reason;
bufref_T bufref;
set_bufref(&bufref, buf);
@@ -4838,6 +4735,7 @@ int buf_check_timestamp(buf_T *buf)
// was set, the global option value otherwise.
reload = RELOAD_NORMAL;
} else {
+ char *reason;
if (!file_info_ok) {
reason = "deleted";
} else if (bufIsChanged(buf)) {
@@ -4864,7 +4762,7 @@ int buf_check_timestamp(buf_T *buf)
if (!bufref_valid(&bufref)) {
emsg(_("E246: FileChangedShell autocommand deleted buffer"));
}
- s = get_vim_var_str(VV_FCS_CHOICE);
+ char *s = get_vim_var_str(VV_FCS_CHOICE);
if (strcmp(s, "reload") == 0 && *reason != 'd') {
reload = RELOAD_NORMAL;
} else if (strcmp(s, "edit") == 0) {
@@ -4917,7 +4815,7 @@ int buf_check_timestamp(buf_T *buf)
}
if (mesg != NULL) {
- path = home_replace_save(buf, buf->b_fname);
+ char *path = home_replace_save(buf, buf->b_fname);
if (!helpmesg) {
mesg2 = "";
}
@@ -5000,8 +4898,6 @@ int buf_check_timestamp(buf_T *buf)
void buf_reload(buf_T *buf, int orig_mode, bool reload_options)
{
exarg_T ea;
- pos_T old_cursor;
- linenr_T old_topline;
int old_ro = buf->b_p_ro;
buf_T *savebuf;
bufref_T bufref;
@@ -5021,8 +4917,8 @@ void buf_reload(buf_T *buf, int orig_mode, bool reload_options)
prep_exarg(&ea, buf);
}
- old_cursor = curwin->w_cursor;
- old_topline = curwin->w_topline;
+ pos_T old_cursor = curwin->w_cursor;
+ linenr_T old_topline = curwin->w_topline;
if (p_ur < 0 || curbuf->b_ml.ml_line_count <= p_ur) {
// Save all the text, so that the reload can be undone.
@@ -5156,11 +5052,11 @@ void write_lnum_adjust(linenr_T offset)
#if defined(BACKSLASH_IN_FILENAME)
/// Convert all backslashes in fname to forward slashes in-place,
/// unless when it looks like a URL.
-void forward_slash(char_u *fname)
+void forward_slash(char *fname)
{
- char_u *p;
+ char *p;
- if (path_with_url((const char *)fname)) {
+ if (path_with_url(fname)) {
return;
}
for (p = fname; *p != NUL; p++) {
@@ -5317,7 +5213,7 @@ int delete_recursive(const char *name)
garray_T ga;
if (readdir_core(&ga, exp, NULL, NULL) == OK) {
for (int i = 0; i < ga.ga_len; i++) {
- vim_snprintf(NameBuff, MAXPATHL, "%s/%s", exp, ((char_u **)ga.ga_data)[i]);
+ vim_snprintf(NameBuff, MAXPATHL, "%s/%s", exp, ((char **)ga.ga_data)[i]);
if (delete_recursive((const char *)NameBuff) != 0) {
// Remember the failure but continue deleting any further
// entries.
@@ -5505,28 +5401,22 @@ bool match_file_pat(char *pattern, regprog_T **prog, char *fname, char *sfname,
/// @param ffname full file name
///
/// @return true if there was a match
-bool match_file_list(char_u *list, char_u *sfname, char_u *ffname)
+bool match_file_list(char *list, char *sfname, char *ffname)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1, 3)
{
- char_u buf[100];
- char_u *tail;
- char_u *regpat;
- char allow_dirs;
- bool match;
- char *p;
-
- tail = (char_u *)path_tail((char *)sfname);
+ char *tail = path_tail(sfname);
// try all patterns in 'wildignore'
- p = (char *)list;
+ char *p = list;
while (*p) {
- copy_option_part(&p, (char *)buf, ARRAY_SIZE(buf), ",");
- regpat = (char_u *)file_pat_to_reg_pat((char *)buf, NULL, &allow_dirs, false);
+ char buf[100];
+ copy_option_part(&p, buf, ARRAY_SIZE(buf), ",");
+ char allow_dirs;
+ char *regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, false);
if (regpat == NULL) {
break;
}
- match = match_file_pat((char *)regpat, NULL, (char *)ffname, (char *)sfname, (char *)tail,
- (int)allow_dirs);
+ bool match = match_file_pat(regpat, NULL, ffname, sfname, tail, (int)allow_dirs);
xfree(regpat);
if (match) {
return true;
@@ -5549,15 +5439,10 @@ bool match_file_list(char_u *list, char_u *sfname, char_u *ffname)
char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs, int no_bslash)
FUNC_ATTR_NONNULL_ARG(1)
{
- const char *endp;
- char *reg_pat;
- const char *p;
- int nested = 0;
- bool add_dollar = true;
-
if (allow_dirs != NULL) {
*allow_dirs = false;
}
+
if (pat_end == NULL) {
pat_end = pat + strlen(pat);
}
@@ -5568,7 +5453,7 @@ char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs
size_t size = 2; // '^' at start, '$' at end.
- for (p = pat; p < pat_end; p++) {
+ for (const char *p = pat; p < pat_end; p++) {
switch (*p) {
case '*':
case '.':
@@ -5589,7 +5474,7 @@ char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs
break;
}
}
- reg_pat = xmalloc(size + 1);
+ char *reg_pat = xmalloc(size + 1);
size_t i = 0;
@@ -5600,14 +5485,16 @@ char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs
} else {
reg_pat[i++] = '^';
}
- endp = pat_end - 1;
+ const char *endp = pat_end - 1;
+ bool add_dollar = true;
if (endp >= pat && *endp == '*') {
while (endp - pat > 0 && *endp == '*') {
endp--;
}
add_dollar = false;
}
- for (p = pat; *p && nested >= 0 && p <= endp; p++) {
+ int nested = 0;
+ for (const char *p = pat; *p && nested >= 0 && p <= endp; p++) {
switch (*p) {
case '*':
reg_pat[i++] = '.';
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index 6cb9e5c38d..7306131574 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -2873,7 +2873,7 @@ static void foldlevelIndent(fline_T *flp)
// empty line or lines starting with a character in 'foldignore': level
// depends on surrounding lines
- if (*s == NUL || vim_strchr(flp->wp->w_p_fdi, *s) != NULL) {
+ if (*s == NUL || vim_strchr(flp->wp->w_p_fdi, (uint8_t)(*s)) != NULL) {
// first and last line can't be undefined, use level 0
if (lnum == 1 || lnum == buf->b_ml.ml_line_count) {
flp->lvl = 0;
diff --git a/src/nvim/fold.h b/src/nvim/fold.h
index 9c3a34ab31..ac1e8c9419 100644
--- a/src/nvim/fold.h
+++ b/src/nvim/fold.h
@@ -20,8 +20,6 @@ typedef struct foldinfo {
linenr_T fi_lines;
} foldinfo_T;
-#define FOLDINFO_INIT { 0, 0, 0, 0 }
-
EXTERN int disable_fold_update INIT(= 0);
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/garray.c b/src/nvim/garray.c
index 0f11868031..aa9a44d410 100644
--- a/src/nvim/garray.c
+++ b/src/nvim/garray.c
@@ -173,9 +173,9 @@ char *ga_concat_strings_sep(const garray_T *gap, const char *sep)
/// @param gap
///
/// @returns the concatenated strings
-char_u *ga_concat_strings(const garray_T *gap) FUNC_ATTR_NONNULL_RET
+char *ga_concat_strings(const garray_T *gap) FUNC_ATTR_NONNULL_RET
{
- return (char_u *)ga_concat_strings_sep(gap, ",");
+ return ga_concat_strings_sep(gap, ",");
}
/// Concatenate a string to a growarray which contains characters.
@@ -216,7 +216,7 @@ void ga_concat_len(garray_T *const gap, const char *restrict s, const size_t len
///
/// @param gap
/// @param c
-void ga_append(garray_T *gap, char c)
+void ga_append(garray_T *gap, uint8_t c)
{
- GA_APPEND(char, gap, c);
+ GA_APPEND(uint8_t, gap, c);
}
diff --git a/src/nvim/garray.h b/src/nvim/garray.h
index 3e2650b410..1623c4db7b 100644
--- a/src/nvim/garray.h
+++ b/src/nvim/garray.h
@@ -27,7 +27,8 @@ typedef struct growarray {
#define GA_APPEND(item_type, gap, item) \
do { \
ga_grow(gap, 1); \
- ((item_type *)(gap)->ga_data)[(gap)->ga_len++] = (item); \
+ ((item_type *)(gap)->ga_data)[(gap)->ga_len] = (item); \
+ (gap)->ga_len++; \
} while (0)
#define GA_APPEND_VIA_PTR(item_type, gap) \
diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua
index 96c9b21b8f..35f6bf8455 100644
--- a/src/nvim/generators/gen_api_dispatch.lua
+++ b/src/nvim/generators/gen_api_dispatch.lua
@@ -426,7 +426,9 @@ for _,fn in ipairs(functions) do
end
remote_fns.redraw = {impl_name="ui_client_redraw", fast=true}
-local hashorder, hashfun = hashy.hashy_hash("msgpack_rpc_get_handler_for", vim.tbl_keys(remote_fns), function (idx)
+local names = vim.tbl_keys(remote_fns)
+table.sort(names)
+local hashorder, hashfun = hashy.hashy_hash("msgpack_rpc_get_handler_for", names, function (idx)
return "method_handlers["..idx.."].name"
end)
diff --git a/src/nvim/generators/gen_eval.lua b/src/nvim/generators/gen_eval.lua
index a50e058e00..baed6a74c2 100644
--- a/src/nvim/generators/gen_eval.lua
+++ b/src/nvim/generators/gen_eval.lua
@@ -73,14 +73,13 @@ for _,fun in ipairs(metadata) do
end
end
+local func_names = vim.tbl_keys(funcs)
+table.sort(func_names)
local funcsdata = io.open(funcs_file, 'w')
-funcsdata:write(mpack.pack(funcs))
+funcsdata:write(mpack.pack(func_names))
funcsdata:close()
-
-local names = vim.tbl_keys(funcs)
-
-local neworder, hashfun = hashy.hashy_hash("find_internal_func", names, function (idx)
+local neworder, hashfun = hashy.hashy_hash("find_internal_func", func_names, function (idx)
return "functions["..idx.."].name"
end)
hashpipe:write("static const EvalFuncDef functions[] = {\n")
diff --git a/src/nvim/generators/gen_events.lua b/src/nvim/generators/gen_events.lua
index 6ee45a14af..8db7f22452 100644
--- a/src/nvim/generators/gen_events.lua
+++ b/src/nvim/generators/gen_events.lua
@@ -32,7 +32,9 @@ for i, event in ipairs(events) do
end
end
-for alias, event in pairs(aliases) do
+for _, v in ipairs(aliases) do
+ local alias = v[1]
+ local event = v[2]
names_tgt:write(('\n {%u, "%s", EVENT_%s},'):format(#alias, alias, event:upper()))
end
diff --git a/src/nvim/generators/gen_keysets.lua b/src/nvim/generators/gen_keysets.lua
index 633c5da184..b1c1f3e2d8 100644
--- a/src/nvim/generators/gen_keysets.lua
+++ b/src/nvim/generators/gen_keysets.lua
@@ -1,4 +1,3 @@
-
local nvimsrcdir = arg[1]
local shared_file = arg[2]
local funcs_file = arg[3]
@@ -38,7 +37,9 @@ local function sanitize(key)
return key
end
-for name, keys in pairs(keysets) do
+for _, v in ipairs(keysets) do
+ local name = v[1]
+ local keys = v[2]
local neworder, hashfun = hashy.hashy_hash(name, keys, function (idx)
return name.."_table["..idx.."].str"
end)
diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua
index af21d44eaf..edb7dae159 100644
--- a/src/nvim/generators/gen_options.lua
+++ b/src/nvim/generators/gen_options.lua
@@ -159,7 +159,7 @@ local dump_option = function(i, o)
if #o.scope == 2 then
pv_name = 'OPT_BOTH(' .. pv_name .. ')'
end
- defines['PV_' .. varname:sub(3):upper()] = pv_name
+ table.insert(defines, { 'PV_' .. varname:sub(3):upper() , pv_name})
w(' .indir=' .. pv_name)
end
if o.enable_if then
@@ -192,7 +192,7 @@ w(' [' .. ('%u'):format(#options.options) .. ']={.fullname=NULL}')
w('};')
w('')
-for k, v in pairs(defines) do
- w('#define ' .. k .. ' ' .. v)
+for _, v in ipairs(defines) do
+ w('#define ' .. v[1] .. ' ' .. v[2])
end
opt_fd:close()
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index b9e3b6b902..8ed9381bca 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -151,11 +151,11 @@ void free_buff(buffheader_T *buf)
/// K_SPECIAL in the returned string is escaped.
///
/// @param dozero count == zero is not an error
-static char_u *get_buffcont(buffheader_T *buffer, int dozero)
+static char *get_buffcont(buffheader_T *buffer, int dozero)
{
size_t count = 0;
- char_u *p = NULL;
- char_u *p2;
+ char *p = NULL;
+ char *p2;
// compute the total length of the string
for (const buffblock_T *bp = buffer->bh_first.b_next;
@@ -168,7 +168,7 @@ static char_u *get_buffcont(buffheader_T *buffer, int dozero)
p2 = p;
for (const buffblock_T *bp = buffer->bh_first.b_next;
bp != NULL; bp = bp->b_next) {
- for (const char_u *str = (char_u *)bp->b_str; *str;) {
+ for (const char *str = bp->b_str; *str;) {
*p2++ = *str++;
}
}
@@ -185,7 +185,7 @@ char_u *get_recorded(void)
char *p;
size_t len;
- p = (char *)get_buffcont(&recordbuff, true);
+ p = get_buffcont(&recordbuff, true);
free_buff(&recordbuff);
// Remove the characters that were added the last time, these must be the
@@ -207,7 +207,7 @@ char_u *get_recorded(void)
/// Return the contents of the redo buffer as a single string.
/// K_SPECIAL in the returned string is escaped.
-char_u *get_inserted(void)
+char *get_inserted(void)
{
return get_buffcont(&redobuff, false);
}
@@ -252,7 +252,7 @@ static void add_buff(buffheader_T *const buf, const char *const s, ptrdiff_t sle
} else {
len = (size_t)slen;
}
- buffblock_T *p = xmalloc(sizeof(buffblock_T) + len);
+ buffblock_T *p = xmalloc(offsetof(buffblock_T, b_str) + len + 1);
buf->bh_space = len - (size_t)slen;
xstrlcpy(p->b_str, s, (size_t)slen + 1);
@@ -475,7 +475,7 @@ void saveRedobuff(save_redo_T *save_redo)
old_redobuff.bh_first.b_next = NULL;
// Make a copy, so that ":normal ." in a function works.
- char *const s = (char *)get_buffcont(&save_redo->sr_redobuff, false);
+ char *const s = get_buffcont(&save_redo->sr_redobuff, false);
if (s == NULL) {
return;
}
@@ -538,7 +538,7 @@ void AppendToRedobuffLit(const char *str, int len)
// Handle a special or multibyte character.
// Composing chars separately are handled separately.
- const int c = mb_cptr2char_adv((const char_u **)&s);
+ const int c = mb_cptr2char_adv(&s);
if (c < ' ' || c == DEL || (*s == NUL && (c == '0' || c == '^'))) {
add_char_buff(&redobuff, Ctrl_V);
}
@@ -599,7 +599,7 @@ void stuffReadbuffSpec(const char *s)
stuffReadbuffLen(s, 3);
s += 3;
} else {
- int c = mb_cptr2char_adv((const char_u **)&s);
+ int c = mb_cptr2char_adv(&s);
if (c == CAR || c == NL || c == ESC) {
c = ' ';
}
@@ -640,7 +640,7 @@ void stuffescaped(const char *arg, bool literally)
// stuff a single special character
if (*arg != NUL) {
- const int c = mb_cptr2char_adv((const char_u **)&arg);
+ const int c = mb_cptr2char_adv(&arg);
if (literally && ((c < ' ' && c != TAB) || c == DEL)) {
stuffcharReadbuff(Ctrl_V);
}
@@ -886,7 +886,7 @@ int ins_typebuf(char *str, int noremap, int offset, bool nottyped, bool silent)
// often.
int newoff = MAXMAPLEN + 4;
int extra = addlen + newoff + 4 * (MAXMAPLEN + 4);
- if (typebuf.tb_len > 2147483674 - extra) {
+ if (typebuf.tb_len > INT_MAX - extra) {
// string is getting too long for 32 bit int
emsg(_(e_toocompl)); // also calls flush_buffers
setcursor();
@@ -2526,10 +2526,12 @@ static int vgetorpeek(bool advance)
// move cursor left, if possible
if (curwin->w_cursor.col != 0) {
if (curwin->w_wcol > 0) {
- if (did_ai) {
- // We are expecting to truncate the trailing
- // white-space, so find the last non-white
- // character -- webb
+ // After auto-indenting and no text is following,
+ // we are expecting to truncate the trailing
+ // white-space, so find the last non-white
+ // character -- webb
+ if (did_ai
+ && *skipwhite(get_cursor_line_ptr() + curwin->w_cursor.col) == NUL) {
curwin->w_wcol = 0;
ptr = (char_u *)get_cursor_line_ptr();
chartabsize_T cts;
@@ -2993,16 +2995,16 @@ char *getcmdkeycmd(int promptc, void *cookie, int indent, bool do_concat)
ga_concat(&line_ga, "<SNR>");
} else {
if (cmod != 0) {
- ga_append(&line_ga, (char)K_SPECIAL);
- ga_append(&line_ga, (char)KS_MODIFIER);
- ga_append(&line_ga, (char)cmod);
+ ga_append(&line_ga, K_SPECIAL);
+ ga_append(&line_ga, KS_MODIFIER);
+ ga_append(&line_ga, (uint8_t)cmod);
}
if (IS_SPECIAL(c1)) {
- ga_append(&line_ga, (char)K_SPECIAL);
- ga_append(&line_ga, (char)K_SECOND(c1));
- ga_append(&line_ga, (char)K_THIRD(c1));
+ ga_append(&line_ga, K_SPECIAL);
+ ga_append(&line_ga, (uint8_t)K_SECOND(c1));
+ ga_append(&line_ga, (uint8_t)K_THIRD(c1));
} else {
- ga_append(&line_ga, (char)c1);
+ ga_append(&line_ga, (uint8_t)c1);
}
}
@@ -3038,7 +3040,7 @@ bool map_execute_lua(void)
} else if (c1 == '\r' || c1 == '\n') {
c1 = NUL; // end the line
} else {
- ga_append(&line_ga, (char)c1);
+ ga_append(&line_ga, (uint8_t)c1);
}
}
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index aa8dbf6331..df4ae05522 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -494,6 +494,9 @@ EXTERN int v_dying INIT(= 0);
EXTERN bool stdin_isatty INIT(= true);
// is stdout a terminal?
EXTERN bool stdout_isatty INIT(= true);
+// is stderr a terminal?
+EXTERN bool stderr_isatty INIT(= true);
+
/// filedesc set by embedder for reading first buffer like `cmd | nvim -`
EXTERN int stdin_fd INIT(= -1);
@@ -771,7 +774,7 @@ EXTERN bool g_tag_at_cursor INIT(= false); // whether the tag command comes
EXTERN int replace_offset INIT(= 0); // offset for replace_push()
-EXTERN char_u *escape_chars INIT(= (char_u *)" \t\\\"|"); // need backslash in cmd line
+EXTERN char *escape_chars INIT(= " \t\\\"|"); // need backslash in cmd line
EXTERN int keep_help_flag INIT(= false); // doing :ta from help file
@@ -803,8 +806,8 @@ enum {
extern char *default_vim_dir;
extern char *default_vimruntime_dir;
extern char *default_lib_dir;
-extern char_u *compiled_user;
-extern char_u *compiled_sys;
+extern char *compiled_user;
+extern char *compiled_sys;
#endif
// When a window has a local directory, the absolute path of the global
@@ -822,7 +825,7 @@ EXTERN int cmdwin_type INIT(= 0); ///< type of cmdline window or 0
EXTERN int cmdwin_result INIT(= 0); ///< result of cmdline window or 0
EXTERN int cmdwin_level INIT(= 0); ///< cmdline recursion level
-EXTERN char_u no_lines_msg[] INIT(= N_("--No lines in buffer--"));
+EXTERN char no_lines_msg[] INIT(= N_("--No lines in buffer--"));
// When ":global" is used to number of substitutions and changed lines is
// accumulated until it's finished.
@@ -999,7 +1002,6 @@ EXTERN char e_fnametoolong[] INIT(= N_("E856: Filename too long"));
EXTERN char e_float_as_string[] INIT(= N_("E806: using Float as a String"));
EXTERN char e_cannot_edit_other_buf[] INIT(= N_("E788: Not allowed to edit another buffer now"));
-EXTERN char e_autocmd_err[] INIT(= N_("E5500: autocmd has thrown an exception: %s"));
EXTERN char e_cmdmap_err[] INIT(= N_("E5520: <Cmd> mapping must end with <CR>"));
EXTERN char e_cmdmap_repeated[]
INIT(= N_("E5521: <Cmd> mapping must end with <CR> before second <Cmd>"));
diff --git a/src/nvim/grid.c b/src/nvim/grid.c
index 4702e224c6..46f8a59710 100644
--- a/src/nvim/grid.c
+++ b/src/nvim/grid.c
@@ -142,16 +142,16 @@ void grid_putchar(ScreenGrid *grid, int c, int row, int col, int attr)
/// Also return its attribute in *attrp;
void grid_getbytes(ScreenGrid *grid, int row, int col, char *bytes, int *attrp)
{
- size_t off;
-
grid_adjust(&grid, &row, &col);
// safety check
- if (grid->chars != NULL && row < grid->rows && col < grid->cols) {
- off = grid->line_offset[row] + (size_t)col;
- *attrp = grid->attrs[off];
- schar_copy(bytes, grid->chars[off]);
+ if (grid->chars == NULL || row >= grid->rows || col >= grid->cols) {
+ return;
}
+
+ size_t off = grid->line_offset[row] + (size_t)col;
+ *attrp = grid->attrs[off];
+ schar_copy(bytes, grid->chars[off]);
}
/// put string '*text' on the window grid at position 'row' and 'col', with
diff --git a/src/nvim/hashtab.c b/src/nvim/hashtab.c
index 042cb43ce4..851e70caca 100644
--- a/src/nvim/hashtab.c
+++ b/src/nvim/hashtab.c
@@ -30,6 +30,7 @@
#include "nvim/hashtab.h"
#include "nvim/memory.h"
#include "nvim/message.h"
+#include "nvim/types.h"
#include "nvim/vim.h"
// Magic value for algorithm that walks through the array.
@@ -87,7 +88,7 @@ void hash_clear_all(hashtab_T *ht, unsigned int off)
/// is changed in any way.
hashitem_T *hash_find(const hashtab_T *const ht, const char *const key)
{
- return hash_lookup(ht, key, strlen(key), hash_hash((char_u *)key));
+ return hash_lookup(ht, key, strlen(key), hash_hash(key));
}
/// Like hash_find, but key is not NUL-terminated
@@ -203,13 +204,13 @@ void hash_debug_results(void)
/// FAIL if key already present
int hash_add(hashtab_T *ht, char *key)
{
- hash_T hash = hash_hash((char_u *)key);
+ hash_T hash = hash_hash(key);
hashitem_T *hi = hash_lookup(ht, key, strlen(key), hash);
if (!HASHITEM_EMPTY(hi)) {
internal_error("hash_add()");
return FAIL;
}
- hash_add_item(ht, hi, (char_u *)key, hash);
+ hash_add_item(ht, hi, key, hash);
return OK;
}
@@ -220,14 +221,14 @@ int hash_add(hashtab_T *ht, char *key)
/// @param key Pointer to the key for the new item. The key has to be contained
/// in the new item (@see hashitem_T). Must not be NULL.
/// @param hash The precomputed hash value for the key.
-void hash_add_item(hashtab_T *ht, hashitem_T *hi, char_u *key, hash_T hash)
+void hash_add_item(hashtab_T *ht, hashitem_T *hi, char *key, hash_T hash)
{
ht->ht_used++;
ht->ht_changed++;
if (hi->hi_key == NULL) {
ht->ht_filled++;
}
- hi->hi_key = (char *)key;
+ hi->hi_key = key;
hi->hi_hash = hash;
// When the space gets low may resize the array.
@@ -405,9 +406,9 @@ static void hash_may_resize(hashtab_T *ht, size_t minitems)
/// run a script that uses hashtables a lot. Vim will then print statistics
/// when exiting. Try that with the current hash algorithm and yours. The
/// lower the percentage the better.
-hash_T hash_hash(const char_u *key)
+hash_T hash_hash(const char *key)
{
- hash_T hash = *key;
+ hash_T hash = (uint8_t)(*key);
if (hash == 0) {
return (hash_T)0;
@@ -415,7 +416,7 @@ hash_T hash_hash(const char_u *key)
// A simplistic algorithm that appears to do very well.
// Suggested by George Reilly.
- const uint8_t *p = key + 1;
+ const uint8_t *p = (uint8_t *)key + 1;
while (*p != NUL) {
HASH_CYCLE_BODY(hash, p);
}
diff --git a/src/nvim/help.c b/src/nvim/help.c
index 0a695a0aa7..bbc552fa4c 100644
--- a/src/nvim/help.c
+++ b/src/nvim/help.c
@@ -412,7 +412,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep
// And also "\_$" and "\_^".
if (arg[0] == '\\'
&& ((arg[1] != NUL && arg[2] == NUL)
- || (vim_strchr("%_z@", arg[1]) != NULL
+ || (vim_strchr("%_z@", (uint8_t)arg[1]) != NULL
&& arg[2] != NUL))) {
vim_snprintf(d, IOSIZE, "/\\\\%s", arg + 1);
// Check for "/\\_$", should be "/\\_\$"
@@ -471,7 +471,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep
// Insert '-' before and after "CTRL-X" when applicable.
if (*s < ' '
|| (*s == '^' && s[1]
- && (ASCII_ISALPHA(s[1]) || vim_strchr("?@[\\]^", s[1]) != NULL))) {
+ && (ASCII_ISALPHA(s[1]) || vim_strchr("?@[\\]^", (uint8_t)s[1]) != NULL))) {
if (d > IObuff && d[-1] != '_' && d[-1] != '\\') {
*d++ = '_'; // prepend a '_' to make x_CTRL-x
}
@@ -555,7 +555,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep
// Sort the matches found on the heuristic number that is after the
// tag name.
qsort((void *)(*matches), (size_t)(*num_matches),
- sizeof(char_u *), help_compare);
+ sizeof(char *), help_compare);
// Delete more than TAG_MANY to reduce the size of the listing.
while (*num_matches > TAG_MANY) {
xfree((*matches)[--*num_matches]);
@@ -799,7 +799,7 @@ void fix_help_buffer(void)
// The text is utf-8 when a byte
// above 127 is found and no
// illegal byte sequence is found.
- if ((char_u)(*s) >= 0x80 && this_utf != kFalse) {
+ if ((uint8_t)(*s) >= 0x80 && this_utf != kFalse) {
this_utf = kTrue;
const int l = utf_ptr2len(s);
if (l == 1) {
@@ -923,7 +923,7 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
// If using the "++t" argument or generating tags for "$VIMRUNTIME/doc"
// add the "help-tags" tag.
- ga_init(&ga, (int)sizeof(char_u *), 100);
+ ga_init(&ga, (int)sizeof(char *), 100);
if (add_help_tags
|| path_full_compare("$VIMRUNTIME/doc", dir, false, true) == kEqualFiles) {
size_t s_len = 18 + strlen(tagfname);
@@ -948,7 +948,7 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
// Detect utf-8 file by a non-ASCII char in the first line.
TriState this_utf8 = kNone;
for (s = IObuff; *s != NUL; s++) {
- if ((char_u)(*s) >= 0x80) {
+ if ((uint8_t)(*s) >= 0x80) {
this_utf8 = kTrue;
const int l = utf_ptr2len(s);
if (l == 1) {
@@ -974,12 +974,12 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
}
if (in_example) {
// skip over example; a non-white in the first column ends it
- if (vim_strchr(" \t\n\r", IObuff[0])) {
+ if (vim_strchr(" \t\n\r", (uint8_t)IObuff[0])) {
continue;
}
in_example = false;
}
- p1 = vim_strchr((char *)IObuff, '*'); // find first '*'
+ p1 = vim_strchr(IObuff, '*'); // find first '*'
while (p1 != NULL) {
p2 = strchr((const char *)p1 + 1, '*'); // Find second '*'.
if (p2 != NULL && p2 > p1 + 1) { // Skip "*" and "**".
@@ -994,7 +994,7 @@ static void helptags_one(char *dir, const char *ext, const char *tagfname, bool
// followed by a white character or end-of-line.
if (s == p2
&& (p1 == IObuff || p1[-1] == ' ' || p1[-1] == '\t')
- && (vim_strchr(" \t\n\r", s[1]) != NULL
+ && (vim_strchr(" \t\n\r", (uint8_t)s[1]) != NULL
|| s[1] == '\0')) {
*p2 = '\0';
p1++;
diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c
index c3a259c87d..c20eac3c28 100644
--- a/src/nvim/highlight.c
+++ b/src/nvim/highlight.c
@@ -649,7 +649,7 @@ int hl_blend_attrs(int back_attr, int front_attr, bool *through)
cattrs = battrs;
cattrs.rgb_fg_color = rgb_blend(ratio, battrs.rgb_fg_color,
fattrs.rgb_bg_color);
- if (cattrs.rgb_ae_attr & (HL_ANY_UNDERLINE)) {
+ if (cattrs.rgb_ae_attr & (HL_UNDERLINE_MASK)) {
cattrs.rgb_sp_color = rgb_blend(ratio, battrs.rgb_sp_color,
fattrs.rgb_bg_color);
} else {
@@ -667,7 +667,7 @@ int hl_blend_attrs(int back_attr, int front_attr, bool *through)
}
cattrs.rgb_fg_color = rgb_blend(ratio/2, battrs.rgb_fg_color,
fattrs.rgb_fg_color);
- if (cattrs.rgb_ae_attr & (HL_ANY_UNDERLINE)) {
+ if (cattrs.rgb_ae_attr & (HL_UNDERLINE_MASK)) {
cattrs.rgb_sp_color = rgb_blend(ratio/2, battrs.rgb_bg_color,
fattrs.rgb_sp_color);
} else {
@@ -825,46 +825,52 @@ void hlattrs2dict(Dictionary *dict, HlAttrs ae, bool use_rgb)
Dictionary hl = *dict;
int mask = use_rgb ? ae.rgb_ae_attr : ae.cterm_ae_attr;
+ if (mask & HL_INVERSE) {
+ PUT_C(hl, "reverse", BOOLEAN_OBJ(true));
+ }
+
if (mask & HL_BOLD) {
PUT_C(hl, "bold", BOOLEAN_OBJ(true));
}
- if (mask & HL_STANDOUT) {
- PUT_C(hl, "standout", BOOLEAN_OBJ(true));
+ if (mask & HL_ITALIC) {
+ PUT_C(hl, "italic", BOOLEAN_OBJ(true));
}
- if (mask & HL_UNDERLINE) {
+ switch (mask & HL_UNDERLINE_MASK) {
+ case HL_UNDERLINE:
PUT_C(hl, "underline", BOOLEAN_OBJ(true));
- }
+ break;
- if (mask & HL_UNDERCURL) {
+ case HL_UNDERCURL:
PUT_C(hl, "undercurl", BOOLEAN_OBJ(true));
- }
+ break;
- if (mask & HL_UNDERDOUBLE) {
+ case HL_UNDERDOUBLE:
PUT_C(hl, "underdouble", BOOLEAN_OBJ(true));
- }
+ break;
- if (mask & HL_UNDERDOTTED) {
+ case HL_UNDERDOTTED:
PUT_C(hl, "underdotted", BOOLEAN_OBJ(true));
- }
+ break;
- if (mask & HL_UNDERDASHED) {
+ case HL_UNDERDASHED:
PUT_C(hl, "underdashed", BOOLEAN_OBJ(true));
+ break;
}
- if (mask & HL_ITALIC) {
- PUT_C(hl, "italic", BOOLEAN_OBJ(true));
- }
-
- if (mask & HL_INVERSE) {
- PUT_C(hl, "reverse", BOOLEAN_OBJ(true));
+ if (mask & HL_STANDOUT) {
+ PUT_C(hl, "standout", BOOLEAN_OBJ(true));
}
if (mask & HL_STRIKETHROUGH) {
PUT_C(hl, "strikethrough", BOOLEAN_OBJ(true));
}
+ if (mask & HL_ALTFONT) {
+ PUT_C(hl, "altfont", BOOLEAN_OBJ(true));
+ }
+
if (mask & HL_NOCOMBINE) {
PUT_C(hl, "nocombine", BOOLEAN_OBJ(true));
}
@@ -920,16 +926,17 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e
m = m | flag; \
}
+ CHECK_FLAG(dict, mask, reverse, , HL_INVERSE);
CHECK_FLAG(dict, mask, bold, , HL_BOLD);
- CHECK_FLAG(dict, mask, standout, , HL_STANDOUT);
+ CHECK_FLAG(dict, mask, italic, , HL_ITALIC);
CHECK_FLAG(dict, mask, underline, , HL_UNDERLINE);
CHECK_FLAG(dict, mask, undercurl, , HL_UNDERCURL);
CHECK_FLAG(dict, mask, underdouble, , HL_UNDERDOUBLE);
CHECK_FLAG(dict, mask, underdotted, , HL_UNDERDOTTED);
CHECK_FLAG(dict, mask, underdashed, , HL_UNDERDASHED);
- CHECK_FLAG(dict, mask, italic, , HL_ITALIC);
- CHECK_FLAG(dict, mask, reverse, , HL_INVERSE);
+ CHECK_FLAG(dict, mask, standout, , HL_STANDOUT);
CHECK_FLAG(dict, mask, strikethrough, , HL_STRIKETHROUGH);
+ CHECK_FLAG(dict, mask, altfont, , HL_ALTFONT);
if (use_rgb) {
CHECK_FLAG(dict, mask, fg_indexed, , HL_FG_INDEXED);
CHECK_FLAG(dict, mask, bg_indexed, , HL_BG_INDEXED);
@@ -1005,13 +1012,14 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e
}
cterm_mask_provided = true;
+ CHECK_FLAG(cterm, cterm_mask, reverse, , HL_INVERSE);
CHECK_FLAG(cterm, cterm_mask, bold, , HL_BOLD);
- CHECK_FLAG(cterm, cterm_mask, standout, , HL_STANDOUT);
+ CHECK_FLAG(cterm, cterm_mask, italic, , HL_ITALIC);
CHECK_FLAG(cterm, cterm_mask, underline, , HL_UNDERLINE);
CHECK_FLAG(cterm, cterm_mask, undercurl, , HL_UNDERCURL);
- CHECK_FLAG(cterm, cterm_mask, italic, , HL_ITALIC);
- CHECK_FLAG(cterm, cterm_mask, reverse, , HL_INVERSE);
+ CHECK_FLAG(cterm, cterm_mask, standout, , HL_STANDOUT);
CHECK_FLAG(cterm, cterm_mask, strikethrough, , HL_STRIKETHROUGH);
+ CHECK_FLAG(cterm, cterm_mask, altfont, , HL_ALTFONT);
CHECK_FLAG(cterm, cterm_mask, nocombine, , HL_NOCOMBINE);
} else if (dict->cterm.type == kObjectTypeArray && dict->cterm.data.array.size == 0) {
// empty list from Lua API should clear all cterm attributes
diff --git a/src/nvim/highlight_defs.h b/src/nvim/highlight_defs.h
index 2557a248c3..95c81ac9db 100644
--- a/src/nvim/highlight_defs.h
+++ b/src/nvim/highlight_defs.h
@@ -15,19 +15,23 @@ typedef enum {
HL_INVERSE = 0x01,
HL_BOLD = 0x02,
HL_ITALIC = 0x04,
+ // The next three bits are all underline styles
+ HL_UNDERLINE_MASK = 0x38,
HL_UNDERLINE = 0x08,
HL_UNDERCURL = 0x10,
- HL_UNDERDOUBLE = 0x20,
- HL_UNDERDOTTED = 0x40,
- HL_UNDERDASHED = 0x80,
- HL_STANDOUT = 0x0100,
- HL_NOCOMBINE = 0x0200,
- HL_STRIKETHROUGH = 0x0400,
+ HL_UNDERDOUBLE = 0x18,
+ HL_UNDERDOTTED = 0x20,
+ HL_UNDERDASHED = 0x28,
+ // 0x30 and 0x38 spare for underline styles
+ HL_STANDOUT = 0x0040,
+ HL_STRIKETHROUGH = 0x0080,
+ HL_ALTFONT = 0x0100,
+ // 0x0200 spare
+ HL_NOCOMBINE = 0x0400,
HL_BG_INDEXED = 0x0800,
HL_FG_INDEXED = 0x1000,
HL_DEFAULT = 0x2000,
HL_GLOBAL = 0x4000,
- HL_ANY_UNDERLINE = HL_UNDERLINE | HL_UNDERDOUBLE | HL_UNDERCURL | HL_UNDERDOTTED | HL_UNDERDASHED,
} HlAttrFlags;
/// Stores a complete highlighting entry, including colors and attributes
diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c
index 404835c4a9..3d91335f55 100644
--- a/src/nvim/highlight_group.c
+++ b/src/nvim/highlight_group.c
@@ -67,32 +67,32 @@ Map(cstr_t, int) highlight_unames = MAP_INIT;
static char *(hl_name_table[]) =
{ "bold", "standout", "underline",
"undercurl", "underdouble", "underdotted", "underdashed",
- "italic", "reverse", "inverse", "strikethrough", "nocombine", "NONE" };
+ "italic", "reverse", "inverse", "strikethrough", "altfont",
+ "nocombine", "NONE" };
static int hl_attr_table[] =
{ HL_BOLD, HL_STANDOUT, HL_UNDERLINE,
HL_UNDERCURL, HL_UNDERDOUBLE, HL_UNDERDOTTED, HL_UNDERDASHED,
- HL_ITALIC, HL_INVERSE, HL_INVERSE, HL_STRIKETHROUGH, HL_NOCOMBINE, 0 };
+ HL_ITALIC, HL_INVERSE, HL_INVERSE, HL_STRIKETHROUGH, HL_ALTFONT,
+ HL_NOCOMBINE, 0 };
/// Structure that stores information about a highlight group.
/// The ID of a highlight group is also called group ID. It is the index in
/// the highlight_ga array PLUS ONE.
typedef struct {
- char_u *sg_name; ///< highlight group name
- char *sg_name_u; ///< uppercase of sg_name
+ char *sg_name; ///< highlight group name
+ char *sg_name_u; ///< uppercase of sg_name
bool sg_cleared; ///< "hi clear" was used
int sg_attr; ///< Screen attr @see ATTR_ENTRY
int sg_link; ///< link to this highlight group ID
int sg_deflink; ///< default link; restored in highlight_clear()
int sg_set; ///< combination of flags in \ref SG_SET
sctx_T sg_deflink_sctx; ///< script where the default link was set
- sctx_T sg_script_ctx; ///< script in which the group was last set
- // for terminal UIs
+ sctx_T sg_script_ctx; ///< script in which the group was last set for terminal UIs
int sg_cterm; ///< "cterm=" highlighting attr
///< (combination of \ref HlAttrFlags)
int sg_cterm_fg; ///< terminal fg color number + 1
int sg_cterm_bg; ///< terminal bg color number + 1
- bool sg_cterm_bold; ///< bold attr was set for light color
- // for RGB UIs
+ bool sg_cterm_bold; ///< bold attr was set for light color for RGB UIs
int sg_gui; ///< "gui=" highlighting attributes
///< (combination of \ref HlAttrFlags)
RgbValue sg_rgb_fg; ///< RGB foreground color
@@ -571,7 +571,7 @@ int highlight_num_groups(void)
}
/// Returns the name of a highlight group.
-char_u *highlight_group_name(int id)
+char *highlight_group_name(int id)
{
return hl_table[id].sg_name;
}
@@ -658,8 +658,6 @@ void init_highlight(bool both, bool reset)
/// @return OK for success, FAIL for failure.
int load_colors(char *name)
{
- char_u *buf;
- int retval = FAIL;
static bool recursive = false;
// When being called recursively, this is probably because setting
@@ -671,13 +669,13 @@ int load_colors(char *name)
recursive = true;
size_t buflen = strlen(name) + 12;
- buf = xmalloc(buflen);
+ char *buf = xmalloc(buflen);
apply_autocmds(EVENT_COLORSCHEMEPRE, name, curbuf->b_fname, false, curbuf);
- snprintf((char *)buf, buflen, "colors/%s.vim", name);
- retval = source_runtime((char *)buf, DIP_START + DIP_OPT);
+ snprintf(buf, buflen, "colors/%s.vim", name);
+ int retval = source_runtime(buf, DIP_START + DIP_OPT);
if (retval == FAIL) {
- snprintf((char *)buf, buflen, "colors/%s.lua", name);
- retval = source_runtime((char *)buf, DIP_START + DIP_OPT);
+ snprintf(buf, buflen, "colors/%s.lua", name);
+ retval = source_runtime(buf, DIP_START + DIP_OPT);
}
xfree(buf);
if (retval == OK) {
@@ -873,25 +871,6 @@ update:
void do_highlight(const char *line, const bool forceit, const bool init)
FUNC_ATTR_NONNULL_ALL
{
- const char *name_end;
- const char *linep;
- const char *key_start;
- const char *arg_start;
- int off;
- int len;
- int attr;
- int id;
- int idx;
- HlGroup item_before;
- bool did_change = false;
- bool dodefault = false;
- bool doclear = false;
- bool dolink = false;
- bool error = false;
- int color;
- bool is_normal_group = false; // "Normal" group
- bool did_highlight_changed = false;
-
// If no argument, list current highlighting.
if (!init && ends_excmd((uint8_t)(*line))) {
for (int i = 1; i <= highlight_ga.ga_len && !got_int; i++) {
@@ -901,9 +880,11 @@ void do_highlight(const char *line, const bool forceit, const bool init)
return;
}
+ bool dodefault = false;
+
// Isolate the name.
- name_end = (const char *)skiptowhite(line);
- linep = (const char *)skipwhite(name_end);
+ const char *name_end = (const char *)skiptowhite(line);
+ const char *linep = (const char *)skipwhite(name_end);
// Check for "default" argument.
if (strncmp(line, "default", (size_t)(name_end - line)) == 0) {
@@ -913,6 +894,9 @@ void do_highlight(const char *line, const bool forceit, const bool init)
linep = (const char *)skipwhite(name_end);
}
+ bool doclear = false;
+ bool dolink = false;
+
// Check for "clear" or "link" argument.
if (strncmp(line, "clear", (size_t)(name_end - line)) == 0) {
doclear = true;
@@ -922,7 +906,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
// ":highlight {group-name}": list highlighting for one group.
if (!doclear && !dolink && ends_excmd((uint8_t)(*linep))) {
- id = syn_name2id_len(line, (size_t)(name_end - line));
+ int id = syn_name2id_len(line, (size_t)(name_end - line));
if (id == 0) {
semsg(_("E411: highlight group not found: %s"), line);
} else {
@@ -1024,11 +1008,11 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
// Find the group name in the table. If it does not exist yet, add it.
- id = syn_check_group(line, (size_t)(name_end - line));
+ int id = syn_check_group(line, (size_t)(name_end - line));
if (id == 0) { // Failed (out of memory).
return;
}
- idx = id - 1; // Index is ID minus one.
+ int idx = id - 1; // Index is ID minus one.
// Return if "default" was used and the group already has settings
if (dodefault && hl_has_settings(idx, true)) {
@@ -1036,8 +1020,8 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
// Make a copy so we can check if any attribute actually changed
- item_before = hl_table[idx];
- is_normal_group = (strcmp(hl_table[idx].sg_name_u, "NORMAL") == 0);
+ HlGroup item_before = hl_table[idx];
+ bool is_normal_group = (strcmp(hl_table[idx].sg_name_u, "NORMAL") == 0);
// Clear the highlighting for ":hi clear {group}" and ":hi clear".
if (doclear || (forceit && init)) {
@@ -1047,11 +1031,16 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
}
+ bool did_change = false;
+ bool error = false;
+
char key[64];
char arg[512];
if (!doclear) {
+ const char *arg_start;
+
while (!ends_excmd((uint8_t)(*linep))) {
- key_start = linep;
+ const char *key_start = linep;
if (*linep == '=') {
semsg(_("E415: unexpected equal sign: %s"), key_start);
error = true;
@@ -1071,7 +1060,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
memcpy(key, key_start, key_len);
key[key_len] = NUL;
- vim_strup((char_u *)key);
+ vim_strup(key);
linep = (const char *)skipwhite(linep);
if (strcmp(key, "NONE") == 0) {
@@ -1128,12 +1117,12 @@ void do_highlight(const char *line, const bool forceit, const bool init)
if (strcmp(key, "TERM") == 0
|| strcmp(key, "CTERM") == 0
|| strcmp(key, "GUI") == 0) {
- attr = 0;
- off = 0;
+ int attr = 0;
+ int off = 0;
int i;
while (arg[off] != NUL) {
for (i = ARRAY_SIZE(hl_attr_table); --i >= 0;) {
- len = (int)strlen(hl_name_table[i]);
+ int len = (int)strlen(hl_name_table[i]);
if (STRNICMP(arg + off, hl_name_table[i], len) == 0) {
attr |= hl_attr_table[i];
off += len;
@@ -1183,6 +1172,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
hl_table[idx].sg_cterm_bold = false;
}
+ int color;
if (ascii_isdigit(*arg)) {
color = atoi(arg);
} else if (STRICMP(arg, "fg") == 0) {
@@ -1203,7 +1193,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
} else {
// Reduce calls to STRICMP a bit, it can be slow.
- off = TOUPPER_ASC(*arg);
+ int off = TOUPPER_ASC(*arg);
int i;
for (i = ARRAY_SIZE(color_names); --i >= 0;) {
if (off == color_names[i][0]
@@ -1360,6 +1350,8 @@ void do_highlight(const char *line, const bool forceit, const bool init)
}
}
+ bool did_highlight_changed = false;
+
if (!error && is_normal_group) {
// Need to update all groups, because they might be using "bg" and/or
// "fg", which have been changed now.
@@ -1471,7 +1463,7 @@ static void highlight_list_one(const int id)
const HlGroup *sgp = &hl_table[id - 1]; // index is ID minus one
bool didh = false;
- if (message_filtered((char *)sgp->sg_name)) {
+ if (message_filtered(sgp->sg_name)) {
return;
}
@@ -1505,7 +1497,7 @@ static void highlight_list_one(const int id)
didh = true;
msg_puts_attr("links to", HL_ATTR(HLF_D));
msg_putchar(' ');
- msg_outtrans((char *)hl_table[hl_table[id - 1].sg_link - 1].sg_name);
+ msg_outtrans(hl_table[hl_table[id - 1].sg_link - 1].sg_name);
}
if (!didh) {
@@ -1527,7 +1519,7 @@ Dictionary get_global_hl_defs(Arena *arena)
hlattrs2dict(&attrs, syn_attr2entry(h->sg_attr), true);
} else if (h->sg_link > 0) {
attrs = arena_dict(arena, 1);
- char *link = (char *)hl_table[h->sg_link - 1].sg_name;
+ char *link = hl_table[h->sg_link - 1].sg_name;
PUT_C(attrs, "link", STRING_OBJ(cstr_as_string(link)));
}
PUT_C(rv, (char *)h->sg_name, DICTIONARY_OBJ(attrs));
@@ -1544,8 +1536,6 @@ Dictionary get_global_hl_defs(Arena *arena)
static bool highlight_list_arg(const int id, bool didh, const int type, int iarg, const char *sarg,
const char *const name)
{
- char buf[100];
-
if (got_int) {
return false;
}
@@ -1554,6 +1544,7 @@ static bool highlight_list_arg(const int id, bool didh, const int type, int iarg
return didh;
}
+ char buf[100];
const char *ts = buf;
if (type == LIST_INT) {
snprintf((char *)buf, sizeof(buf), "%d", iarg - 1);
@@ -1562,12 +1553,17 @@ static bool highlight_list_arg(const int id, bool didh, const int type, int iarg
} else { // type == LIST_ATTR
buf[0] = NUL;
for (int i = 0; hl_attr_table[i] != 0; i++) {
- if (iarg & hl_attr_table[i]) {
+ if (((hl_attr_table[i] & HL_UNDERLINE_MASK)
+ && ((iarg & HL_UNDERLINE_MASK) == hl_attr_table[i]))
+ || (!(hl_attr_table[i] & HL_UNDERLINE_MASK)
+ && (iarg & hl_attr_table[i]))) {
if (buf[0] != NUL) {
xstrlcat(buf, ",", 100);
}
xstrlcat(buf, hl_name_table[i], 100);
- iarg &= ~hl_attr_table[i]; // don't want "inverse"
+ if (!(hl_attr_table[i] & HL_UNDERLINE_MASK)) {
+ iarg &= ~hl_attr_table[i]; // don't want "inverse"
+ }
}
}
}
@@ -1594,19 +1590,24 @@ static bool highlight_list_arg(const int id, bool didh, const int type, int iarg
const char *highlight_has_attr(const int id, const int flag, const int modec)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
{
- int attr;
-
if (id <= 0 || id > highlight_ga.ga_len) {
return NULL;
}
+ int attr;
+
if (modec == 'g') {
attr = hl_table[id - 1].sg_gui;
} else {
attr = hl_table[id - 1].sg_cterm;
}
- return (attr & flag) ? "1" : NULL;
+ if (flag & HL_UNDERLINE_MASK) {
+ int ul = attr & HL_UNDERLINE_MASK;
+ return ul == flag ? "1" : NULL;
+ } else {
+ return (attr & flag) ? "1" : NULL;
+ }
}
/// Return color name of the given highlight group
@@ -1622,7 +1623,6 @@ const char *highlight_color(const int id, const char *const what, const int mode
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
static char name[20];
- int n;
bool fg = false;
bool sp = false;
bool font = false;
@@ -1641,6 +1641,9 @@ const char *highlight_color(const int id, const char *const what, const int mode
} else if (!(TOLOWER_ASC(what[0]) == 'b' && TOLOWER_ASC(what[1]) == 'g')) {
return NULL;
}
+
+ int n;
+
if (modec == 'g') {
if (what[2] == '#' && ui_rgb_attached()) {
if (fg) {
@@ -1702,7 +1705,7 @@ bool syn_list_header(const bool did_header, const int outlen, const int id, bool
if (got_int) {
return true;
}
- msg_outtrans((char *)hl_table[id - 1].sg_name);
+ msg_outtrans(hl_table[id - 1].sg_name);
name_col = msg_col;
endcol = 15;
} else if ((ui_has(kUIMessages) || msg_silent) && !force_newline) {
@@ -1795,7 +1798,7 @@ int syn_name2id_len(const char *name, size_t len)
// Avoid alloc()/free(), these are slow too.
memcpy(name_u, name, len);
name_u[len] = '\0';
- vim_strup((char_u *)name_u);
+ vim_strup(name_u);
// map_get(..., int) returns 0 when no key is present, which is
// the expected value for missing highlight group.
@@ -1804,10 +1807,10 @@ int syn_name2id_len(const char *name, size_t len)
/// Lookup a highlight group name and return its attributes.
/// Return zero if not found.
-int syn_name2attr(const char_u *name)
+int syn_name2attr(const char *name)
FUNC_ATTR_NONNULL_ALL
{
- int id = syn_name2id((char *)name);
+ int id = syn_name2id(name);
if (id != 0) {
return syn_id2attr(id);
@@ -1823,10 +1826,10 @@ int highlight_exists(const char *name)
/// Return the name of highlight group "id".
/// When not a valid ID return an empty string.
-char_u *syn_id2name(int id)
+char *syn_id2name(int id)
{
if (id <= 0 || id > highlight_ga.ga_len) {
- return (char_u *)"";
+ return "";
}
return hl_table[id - 1].sg_name;
}
@@ -1896,7 +1899,7 @@ static int syn_add_group(const char *name, size_t len)
// Append another syntax_highlight entry.
HlGroup *hlgp = GA_APPEND_VIA_PTR(HlGroup, &highlight_ga);
CLEAR_POINTER(hlgp);
- hlgp->sg_name = (char_u *)arena_memdupz(&highlight_arena, name, len);
+ hlgp->sg_name = arena_memdupz(&highlight_arena, name, len);
hlgp->sg_rgb_bg = -1;
hlgp->sg_rgb_fg = -1;
hlgp->sg_rgb_sp = -1;
@@ -1908,7 +1911,7 @@ static int syn_add_group(const char *name, size_t len)
hlgp->sg_parent = scoped_parent;
// will get set to false by caller if settings are added
hlgp->sg_cleared = true;
- vim_strup((char_u *)hlgp->sg_name_u);
+ vim_strup(hlgp->sg_name_u);
int id = highlight_ga.ga_len; // ID is index plus one
@@ -2048,17 +2051,15 @@ static void combine_stl_hlt(int id, int id_S, int id_alt, int hlcnt, int i, int
/// screen redraw after any :highlight command.
void highlight_changed(void)
{
- int id;
char userhl[30]; // use 30 to avoid compiler warning
int id_S = -1;
int id_SNC = 0;
- int hlcnt;
need_highlight_changed = false;
/// Translate builtin highlight groups into attributes for quick lookup.
for (int hlf = 0; hlf < HLF_COUNT; hlf++) {
- id = syn_check_group(hlf_names[hlf], strlen(hlf_names[hlf]));
+ int id = syn_check_group(hlf_names[hlf], strlen(hlf_names[hlf]));
if (id == 0) {
abort();
}
@@ -2097,7 +2098,7 @@ void highlight_changed(void)
// Must to be in there simultaneously in case of table overflows in
// get_attr_entry()
ga_grow(&highlight_ga, 10);
- hlcnt = highlight_ga.ga_len;
+ int hlcnt = highlight_ga.ga_len;
if (id_S == -1) {
// Make sure id_S is always valid to simplify code below. Use the last entry
CLEAR_POINTER(&hl_table[hlcnt + 9]);
@@ -2105,7 +2106,7 @@ void highlight_changed(void)
}
for (int i = 0; i < 9; i++) {
snprintf(userhl, sizeof(userhl), "User%d", i + 1);
- id = syn_name2id(userhl);
+ int id = syn_name2id(userhl);
if (id == 0) {
highlight_user[i] = 0;
highlight_stlnc[i] = 0;
@@ -2171,12 +2172,10 @@ void set_context_in_highlight_cmd(expand_T *xp, const char *arg)
/// List highlighting matches in a nice way.
static void highlight_list(void)
{
- int i;
-
- for (i = 10; --i >= 0;) {
+ for (int i = 10; --i >= 0;) {
highlight_list_two(i, HL_ATTR(HLF_D));
}
- for (i = 40; --i >= 0;) {
+ for (int i = 40; --i >= 0;) {
highlight_list_two(99, 0);
}
}
@@ -2921,9 +2920,9 @@ color_name_table_T color_name_table[] = {
/// return the hex value or -1 if could not find a correct value
RgbValue name_to_color(const char *name, int *idx)
{
- if (name[0] == '#' && isxdigit(name[1]) && isxdigit(name[2])
- && isxdigit(name[3]) && isxdigit(name[4]) && isxdigit(name[5])
- && isxdigit(name[6]) && name[7] == NUL) {
+ if (name[0] == '#' && isxdigit((uint8_t)name[1]) && isxdigit((uint8_t)name[2])
+ && isxdigit((uint8_t)name[3]) && isxdigit((uint8_t)name[4]) && isxdigit((uint8_t)name[5])
+ && isxdigit((uint8_t)name[6]) && name[7] == NUL) {
// rgb hex string
*idx = kColorIdxHex;
return (RgbValue)strtol((char *)(name + 1), NULL, 16);
@@ -2947,7 +2946,6 @@ RgbValue name_to_color(const char *name, int *idx)
} else { // found match
*idx = m;
return color_name_table[m].color;
- break;
}
}
diff --git a/src/nvim/iconv.h b/src/nvim/iconv.h
index 509f83c415..f5f3f25786 100644
--- a/src/nvim/iconv.h
+++ b/src/nvim/iconv.h
@@ -1,20 +1,18 @@
#ifndef NVIM_ICONV_H
#define NVIM_ICONV_H
-#include "auto/config.h"
+#include <errno.h>
+#include <iconv.h>
-#ifdef HAVE_ICONV
-# include <errno.h>
-# include <iconv.h>
+#include "auto/config.h"
// define some missing constants if necessary
-# ifndef EILSEQ
-# define EILSEQ 123
-# endif
-# define ICONV_ERRNO errno
-# define ICONV_E2BIG E2BIG
-# define ICONV_EINVAL EINVAL
-# define ICONV_EILSEQ EILSEQ
+#ifndef EILSEQ
+# define EILSEQ 123
#endif
+#define ICONV_ERRNO errno
+#define ICONV_E2BIG E2BIG
+#define ICONV_EINVAL EINVAL
+#define ICONV_EILSEQ EILSEQ
#endif // NVIM_ICONV_H
diff --git a/src/nvim/indent.c b/src/nvim/indent.c
index be1dfb77cf..ec6c72da6d 100644
--- a/src/nvim/indent.c
+++ b/src/nvim/indent.c
@@ -17,6 +17,7 @@
#include "nvim/edit.h"
#include "nvim/eval.h"
#include "nvim/eval/typval_defs.h"
+#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/extmark.h"
#include "nvim/gettext.h"
@@ -24,6 +25,7 @@
#include "nvim/indent.h"
#include "nvim/indent_c.h"
#include "nvim/mark.h"
+#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
@@ -386,7 +388,7 @@ int get_indent_buf(buf_T *buf, linenr_T lnum)
/// Count the size (in window cells) of the indent in line "ptr", with
/// 'tabstop' at "ts".
/// If @param list is true, count only screen size for tabs.
-int get_indent_str(const char_u *ptr, int ts, bool list)
+int get_indent_str(const char *ptr, int ts, bool list)
FUNC_ATTR_NONNULL_ALL
{
int count = 0;
@@ -400,7 +402,7 @@ int get_indent_str(const char_u *ptr, int ts, bool list)
} else {
// In list mode, when tab is not set, count screen char width
// for Tab, displays: ^I
- count += ptr2cells((char *)ptr);
+ count += ptr2cells(ptr);
}
} else if (*ptr == ' ') {
// Count a space for one.
@@ -803,7 +805,7 @@ int get_breakindent_win(win_T *wp, char *line)
{
static int prev_indent = 0; // Cached indent value.
static long prev_ts = 0L; // Cached tabstop value.
- static const char_u *prev_line = NULL; // cached pointer to line.
+ static const char *prev_line = NULL; // cached pointer to line.
static varnumber_T prev_tick = 0; // Changedtick of cached value.
static long *prev_vts = NULL; // Cached vartabs values.
static int prev_list = 0; // cached list value
@@ -820,12 +822,12 @@ int get_breakindent_win(win_T *wp, char *line)
// - 'tabstop' changed
// - 'briopt_list changed' changed or
// - 'formatlistpattern' changed
- if (prev_line != (char_u *)line || prev_ts != wp->w_buffer->b_p_ts
+ if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts
|| prev_tick != buf_get_changedtick(wp->w_buffer)
|| prev_listopt != wp->w_briopt_list
|| (prev_flp == NULL || (strcmp(prev_flp, get_flp_value(wp->w_buffer)) != 0))
|| prev_vts != wp->w_buffer->b_p_vts_array) {
- prev_line = (char_u *)line;
+ prev_line = line;
prev_ts = wp->w_buffer->b_p_ts;
prev_tick = buf_get_changedtick(wp->w_buffer);
prev_vts = wp->w_buffer->b_p_vts_array;
@@ -850,7 +852,7 @@ int get_breakindent_win(win_T *wp, char *line)
if (wp->w_briopt_list > 0) {
prev_list += wp->w_briopt_list;
} else {
- prev_list = (int)(*regmatch.endp - *regmatch.startp);
+ prev_indent = (int)(*regmatch.endp - *regmatch.startp);
}
}
vim_regfree(regmatch.regprog);
@@ -869,17 +871,13 @@ int get_breakindent_win(win_T *wp, char *line)
bri += win_col_off2(wp);
// add additional indent for numbered lists
- if (wp->w_briopt_list != 0) {
- if (wp->w_briopt_list > 0) {
- bri += prev_list;
- } else {
- bri = prev_list;
- }
+ if (wp->w_briopt_list > 0) {
+ bri += prev_list;
}
// indent minus the length of the showbreak string
if (wp->w_briopt_sbr) {
- bri -= vim_strsize((char *)get_showbreak_value(wp));
+ bri -= vim_strsize(get_showbreak_value(wp));
}
// never indent past left window margin
@@ -901,10 +899,10 @@ int get_breakindent_win(win_T *wp, char *line)
// the line.
int inindent(int extra)
{
- char_u *ptr;
+ char *ptr;
colnr_T col;
- for (col = 0, ptr = (char_u *)get_cursor_line_ptr(); ascii_iswhite(*ptr); col++) {
+ for (col = 0, ptr = get_cursor_line_ptr(); ascii_iswhite(*ptr); col++) {
ptr++;
}
@@ -1187,7 +1185,7 @@ int get_lisp_indent(void)
{
pos_T *pos, realpos, paren;
int amount;
- char_u *that;
+ char *that;
colnr_T col;
colnr_T firsttry;
int parencount;
@@ -1222,7 +1220,7 @@ int get_lisp_indent(void)
continue;
}
- for (that = (char_u *)get_cursor_line_ptr(); *that != NUL; that++) {
+ for (that = get_cursor_line_ptr(); *that != NUL; that++) {
if (*that == ';') {
while (*(that + 1) != NUL) {
that++;
@@ -1272,20 +1270,20 @@ int get_lisp_indent(void)
curwin->w_cursor.col = pos->col;
col = pos->col;
- that = (char_u *)get_cursor_line_ptr();
+ that = get_cursor_line_ptr();
if (vi_lisp && (get_indent() == 0)) {
amount = 2;
} else {
- char_u *line = that;
+ char *line = that;
chartabsize_T cts;
- init_chartabsize_arg(&cts, curwin, pos->lnum, 0, (char *)line, (char *)line);
+ init_chartabsize_arg(&cts, curwin, pos->lnum, 0, line, line);
while (*cts.cts_ptr != NUL && col > 0) {
cts.cts_vcol += lbr_chartabsize_adv(&cts);
col--;
}
amount = cts.cts_vcol;
- that = (char_u *)cts.cts_ptr;
+ that = cts.cts_ptr;
clear_chartabsize_arg(&cts);
// Some keywords require "body" indenting rules (the
@@ -1293,7 +1291,7 @@ int get_lisp_indent(void)
// (let ((a 1)) instead (let ((a 1))
// (...)) of (...))
if (!vi_lisp && ((*that == '(') || (*that == '['))
- && lisp_match((char *)that + 1)) {
+ && lisp_match(that + 1)) {
amount += 2;
} else {
if (*that != NUL) {
@@ -1303,12 +1301,12 @@ int get_lisp_indent(void)
firsttry = amount;
init_chartabsize_arg(&cts, curwin, (colnr_T)(that - line),
- amount, (char *)line, (char *)that);
+ amount, line, that);
while (ascii_iswhite(*cts.cts_ptr)) {
cts.cts_vcol += lbr_chartabsize(&cts);
cts.cts_ptr++;
}
- that = (char_u *)cts.cts_ptr;
+ that = cts.cts_ptr;
amount = cts.cts_vcol;
clear_chartabsize_arg(&cts);
@@ -1324,9 +1322,10 @@ int get_lisp_indent(void)
quotecount = 0;
init_chartabsize_arg(&cts, curwin,
- (colnr_T)(that - line), amount, (char *)line, (char *)that);
+ (colnr_T)(that - line), amount, line, that);
if (vi_lisp || ((*that != '"') && (*that != '\'')
- && (*that != '#') && ((*that < '0') || (*that > '9')))) {
+ && (*that != '#')
+ && (((uint8_t)(*that) < '0') || ((uint8_t)(*that) > '9')))) {
while (*cts.cts_ptr
&& (!ascii_iswhite(*cts.cts_ptr) || quotecount || parencount)
&& (!((*cts.cts_ptr == '(' || *cts.cts_ptr == '[')
@@ -1352,7 +1351,7 @@ int get_lisp_indent(void)
cts.cts_vcol += lbr_chartabsize(&cts);
cts.cts_ptr++;
}
- that = (char_u *)cts.cts_ptr;
+ that = cts.cts_ptr;
amount = cts.cts_vcol;
clear_chartabsize_arg(&cts);
@@ -1375,7 +1374,7 @@ static int lisp_match(char *p)
{
char buf[LSIZE];
int len;
- char *word = (char *)(*curbuf->b_p_lw != NUL ? (char_u *)curbuf->b_p_lw : p_lispwords);
+ char *word = *curbuf->b_p_lw != NUL ? curbuf->b_p_lw : p_lispwords;
while (*word != NUL) {
(void)copy_option_part(&word, buf, LSIZE, ",");
diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c
index ccf4448e93..1c771073b2 100644
--- a/src/nvim/indent_c.c
+++ b/src/nvim/indent_c.c
@@ -23,7 +23,6 @@
#include "nvim/pos.h"
#include "nvim/search.h"
#include "nvim/strings.h"
-#include "nvim/types.h"
#include "nvim/vim.h"
// Find result cache for cpp_baseclass
@@ -705,7 +704,7 @@ static int cin_get_equal_amount(linenr_T lnum)
s = ml_get(lnum);
line = s;
- while (*s != NUL && vim_strchr("=;{}\"'", *s) == NULL) {
+ while (*s != NUL && vim_strchr("=;{}\"'", (uint8_t)(*s)) == NULL) {
if (cin_iscomment(s)) { // ignore comments
s = cin_skipcomment(s);
} else {
diff --git a/src/nvim/input.c b/src/nvim/input.c
index 0f0af9d5f0..96214d45c2 100644
--- a/src/nvim/input.c
+++ b/src/nvim/input.c
@@ -29,7 +29,8 @@
# include "input.c.generated.h" // IWYU pragma: export
#endif
-/// Ask for a reply from the user, 'y' or 'n'
+/// Ask for a reply from the user, a 'y' or a 'n', with prompt "str" (which
+/// should have been translated already).
///
/// No other characters are accepted, the message is repeated until a valid
/// reply is entered or <C-c> is hit.
diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c
index fa8e78f624..6de3b0a9d0 100644
--- a/src/nvim/insexpand.c
+++ b/src/nvim/insexpand.c
@@ -7,6 +7,7 @@
#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -597,7 +598,7 @@ static char *ins_compl_infercase_gettext(const char *str, int char_len, int comp
// Allocate wide character array for the completion and fill it.
int *const wca = xmalloc((size_t)char_len * sizeof(*wca));
{
- const char_u *p = (char_u *)str;
+ const char *p = str;
for (int i = 0; i < char_len; i++) {
wca[i] = mb_ptr2char_adv(&p);
}
@@ -605,7 +606,7 @@ static char *ins_compl_infercase_gettext(const char *str, int char_len, int comp
// Rule 1: Were any chars converted to lower?
{
- const char_u *p = (char_u *)compl_orig_text;
+ const char *p = compl_orig_text;
for (int i = 0; i < min_len; i++) {
const int c = mb_ptr2char_adv(&p);
if (mb_islower(c)) {
@@ -624,7 +625,7 @@ static char *ins_compl_infercase_gettext(const char *str, int char_len, int comp
// Rule 2: No lower case, 2nd consecutive letter converted to
// upper case.
if (!has_lower) {
- const char_u *p = (char_u *)compl_orig_text;
+ const char *p = compl_orig_text;
for (int i = 0; i < min_len; i++) {
const int c = mb_ptr2char_adv(&p);
if (was_letter && mb_isupper(c) && mb_islower(wca[i])) {
@@ -640,7 +641,7 @@ static char *ins_compl_infercase_gettext(const char *str, int char_len, int comp
// Copy the original case of the part we typed.
{
- const char_u *p = (char_u *)compl_orig_text;
+ const char *p = compl_orig_text;
for (int i = 0; i < min_len; i++) {
const int c = mb_ptr2char_adv(&p);
if (mb_islower(c)) {
@@ -2257,14 +2258,14 @@ static void copy_global_to_buflocal_cb(Callback *globcb, Callback *bufcb)
/// Invoked when the 'completefunc' option is set. The option value can be a
/// name of a function (string), or function(<name>) or funcref(<name>) or a
/// lambda expression.
-int set_completefunc_option(void)
+void set_completefunc_option(char **errmsg)
{
- int retval = option_set_callback_func(curbuf->b_p_cfu, &cfu_cb);
- if (retval == OK) {
- set_buflocal_cfu_callback(curbuf);
+ if (option_set_callback_func(curbuf->b_p_cfu, &cfu_cb) == FAIL) {
+ *errmsg = e_invarg;
+ return;
}
- return retval;
+ set_buflocal_cfu_callback(curbuf);
}
/// Copy the global 'completefunc' callback function to the buffer-local
@@ -2278,14 +2279,13 @@ void set_buflocal_cfu_callback(buf_T *buf)
/// Invoked when the 'omnifunc' option is set. The option value can be a
/// name of a function (string), or function(<name>) or funcref(<name>) or a
/// lambda expression.
-int set_omnifunc_option(void)
+void set_omnifunc_option(buf_T *buf, char **errmsg)
{
- int retval = option_set_callback_func(curbuf->b_p_ofu, &ofu_cb);
- if (retval == OK) {
- set_buflocal_ofu_callback(curbuf);
+ if (option_set_callback_func(buf->b_p_ofu, &ofu_cb) == FAIL) {
+ *errmsg = e_invarg;
+ return;
}
-
- return retval;
+ set_buflocal_ofu_callback(buf);
}
/// Copy the global 'omnifunc' callback function to the buffer-local 'omnifunc'
@@ -2299,7 +2299,7 @@ void set_buflocal_ofu_callback(buf_T *buf)
/// Invoked when the 'thesaurusfunc' option is set. The option value can be a
/// name of a function (string), or function(<name>) or funcref(<name>) or a
/// lambda expression.
-int set_thesaurusfunc_option(void)
+void set_thesaurusfunc_option(char **errmsg)
{
int retval;
@@ -2311,7 +2311,9 @@ int set_thesaurusfunc_option(void)
retval = option_set_callback_func(p_tsrfu, &tsrfu_cb);
}
- return retval;
+ if (retval == FAIL) {
+ *errmsg = e_invarg;
+ }
}
/// Mark the global 'completefunc' 'omnifunc' and 'thesaurusfunc' callbacks with
@@ -2856,7 +2858,7 @@ static int process_next_cpt_value(ins_compl_next_state_T *st, int *compl_type_ar
// Remember the first match so that the loop stops when we
// wrap and come back there a second time.
st->set_match_pos = true;
- } else if (vim_strchr("buwU", *st->e_cpt) != NULL
+ } else if (vim_strchr("buwU", (uint8_t)(*st->e_cpt)) != NULL
&& (st->ins_buf = ins_compl_next_buf(st->ins_buf, *st->e_cpt)) != curbuf) {
// Scan a buffer, but not the current one.
if (st->ins_buf->b_ml.ml_mfp != NULL) { // loaded buffer
@@ -2950,7 +2952,7 @@ static void get_next_dict_tsr_completion(int compl_type, char *dict, int dict_f)
} else {
ins_compl_dictionaries(dict != NULL ? dict
: (compl_type == CTRL_X_THESAURUS
- ? (*curbuf->b_p_tsr == NUL ? (char *)p_tsr : curbuf->b_p_tsr)
+ ? (*curbuf->b_p_tsr == NUL ? p_tsr : curbuf->b_p_tsr)
: (*curbuf->b_p_dict ==
NUL ? p_dict : curbuf->b_p_dict)),
compl_pattern,
@@ -2996,7 +2998,7 @@ static void get_next_filename_completion(void)
#ifdef BACKSLASH_IN_FILENAME
if (curbuf->b_p_csl[0] != NUL) {
for (int i = 0; i < num_matches; i++) {
- char_u *ptr = matches[i];
+ char *ptr = matches[i];
while (*ptr != NUL) {
if (curbuf->b_p_csl[0] == 's' && *ptr == '\\') {
*ptr = '/';
@@ -3160,7 +3162,7 @@ static int get_next_default_completion(ins_compl_next_state_T *st, pos_T *start_
compl_direction, compl_pattern);
} else {
found_new_match = searchit(NULL, st->ins_buf, st->cur_match_pos,
- NULL, compl_direction, (char_u *)compl_pattern, 1L,
+ NULL, compl_direction, compl_pattern, 1L,
SEARCH_KEEP + SEARCH_NFMSG, RE_LAST, NULL);
}
msg_silent--;
diff --git a/src/nvim/keycodes.c b/src/nvim/keycodes.c
index a4228fcc7e..e19806e464 100644
--- a/src/nvim/keycodes.c
+++ b/src/nvim/keycodes.c
@@ -474,7 +474,7 @@ char_u *get_special_key_name(int c, int modifiers)
int i, idx;
int table_idx;
- char_u *s;
+ char *s;
string[0] = '<';
idx = 1;
@@ -543,7 +543,7 @@ char_u *get_special_key_name(int c, int modifiers)
} else {
s = transchar(c);
while (*s) {
- string[idx++] = *s++;
+ string[idx++] = (uint8_t)(*s++);
}
}
}
@@ -572,7 +572,7 @@ char_u *get_special_key_name(int c, int modifiers)
/// @param[out] did_simplify found <C-H>, etc.
///
/// @return Number of characters added to dst, zero for no match.
-unsigned int trans_special(const char **const srcp, const size_t src_len, char_u *const dst,
+unsigned int trans_special(const char **const srcp, const size_t src_len, char *const dst,
const int flags, const bool escape_ks, bool *const did_simplify)
FUNC_ATTR_NONNULL_ARG(1, 3) FUNC_ATTR_WARN_UNUSED_RESULT
{
@@ -582,7 +582,7 @@ unsigned int trans_special(const char **const srcp, const size_t src_len, char_u
return 0;
}
- return special_to_buf(key, modifiers, escape_ks, dst);
+ return special_to_buf(key, modifiers, escape_ks, (char_u *)dst);
}
/// Put the character sequence for "key" with "modifiers" into "dst" and return
@@ -629,11 +629,11 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m
const int flags, bool *const did_simplify)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1, 3)
{
- const char_u *last_dash;
- const char_u *end_of_name;
- const char_u *src;
- const char_u *bp;
- const char_u *const end = (char_u *)(*srcp) + src_len - 1;
+ const char *last_dash;
+ const char *end_of_name;
+ const char *src;
+ const char *bp;
+ const char *const end = *srcp + src_len - 1;
const bool in_string = flags & FSK_IN_STRING;
int modifiers;
int bit;
@@ -645,7 +645,7 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m
return 0;
}
- src = (char_u *)(*srcp);
+ src = *srcp;
if (src[0] != '<') {
return 0;
}
@@ -659,7 +659,7 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m
if (*bp == '-') {
last_dash = bp;
if (bp + 1 <= end) {
- l = utfc_ptr2len_len((char *)bp + 1, (int)(end - bp) + 1);
+ l = utfc_ptr2len_len(bp + 1, (int)(end - bp) + 1);
// Anything accepted, like <C-?>.
// <C-"> or <M-"> are not special in strings as " is
// the string delimiter. With a backslash it works: <M-\">
@@ -674,7 +674,7 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m
if (end - bp > 3 && bp[0] == 't' && bp[1] == '_') {
bp += 3; // skip t_xx, xx may be '-' or '>'
} else if (end - bp > 4 && STRNICMP(bp, "char-", 5) == 0) {
- vim_str2nr((char *)bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0, true);
+ vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0, true);
if (l == 0) {
emsg(_(e_invarg));
return 0;
@@ -691,7 +691,7 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m
modifiers = 0x0;
for (bp = src + 1; bp < last_dash; bp++) {
if (*bp != '-') {
- bit = name_to_mod_mask(*bp);
+ bit = name_to_mod_mask((uint8_t)(*bp));
if (bit == 0x0) {
break; // Illegal modifier name
}
@@ -704,7 +704,7 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m
if (STRNICMP(last_dash + 1, "char-", 5) == 0
&& ascii_isdigit(last_dash[6])) {
// <Char-123> or <Char-033> or <Char-0x33>
- vim_str2nr((char *)last_dash + 6, NULL, &l, STR2NR_ALL, NULL, &n, 0, true);
+ vim_str2nr(last_dash + 6, NULL, &l, STR2NR_ALL, NULL, &n, 0, true);
if (l == 0) {
emsg(_(e_invarg));
return 0;
@@ -718,12 +718,12 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m
// Special case for a double-quoted string
off = l = 2;
} else {
- l = utfc_ptr2len((char *)last_dash + 1);
+ l = utfc_ptr2len(last_dash + 1);
}
if (modifiers != 0 && last_dash[l + 1] == '>') {
- key = utf_ptr2char((char *)last_dash + off);
+ key = utf_ptr2char(last_dash + off);
} else {
- key = get_special_key_code(last_dash + off);
+ key = get_special_key_code((char_u *)last_dash + off);
if (!(flags & FSK_KEEP_X_KEY)) {
key = handle_x_keys(key);
}
@@ -753,7 +753,7 @@ int find_special_key(const char **const srcp, const size_t src_len, int *const m
}
*modp = modifiers;
- *srcp = (char *)end_of_name;
+ *srcp = end_of_name;
return key;
} // else { ELOG("unknown key: '%s'", src); }
}
@@ -944,7 +944,7 @@ char *replace_termcodes(const char *const from, const size_t from_len, char **co
}
}
- slen = trans_special(&src, (size_t)(end - src) + 1, (char_u *)result + dlen,
+ slen = trans_special(&src, (size_t)(end - src) + 1, result + dlen,
FSK_KEYCODE | ((flags & REPTERM_NO_SIMPLIFY) ? 0 : FSK_SIMPLIFY),
true, did_simplify);
if (slen) {
@@ -1059,8 +1059,8 @@ char *vim_strsave_escape_ks(char *p)
// Need a buffer to hold up to three times as much. Four in case of an
// illegal utf-8 byte:
// 0xc0 -> 0xc3 - 0x80 -> 0xc3 K_SPECIAL KS_SPECIAL KE_FILLER
- char_u *res = xmalloc(strlen(p) * 4 + 1);
- char_u *d = res;
+ char *res = xmalloc(strlen(p) * 4 + 1);
+ char_u *d = (char_u *)res;
for (char_u *s = (char_u *)p; *s != NUL;) {
if (s[0] == K_SPECIAL && s[1] != NUL && s[2] != NUL) {
// Copy special key unmodified.
@@ -1076,7 +1076,7 @@ char *vim_strsave_escape_ks(char *p)
}
*d = NUL;
- return (char *)res;
+ return res;
}
/// Remove escaping from K_SPECIAL characters. Reverse of
diff --git a/src/nvim/linematch.c b/src/nvim/linematch.c
index 629a31c913..a9dac40731 100644
--- a/src/nvim/linematch.c
+++ b/src/nvim/linematch.c
@@ -9,7 +9,6 @@
#include "nvim/linematch.h"
#include "nvim/macros.h"
#include "nvim/memory.h"
-#include "nvim/vim.h"
// struct for running the diff linematch algorithm
typedef struct {
diff --git a/src/nvim/locale.c b/src/nvim/locale.c
index 6322271073..c3cfd3bedb 100644
--- a/src/nvim/locale.c
+++ b/src/nvim/locale.c
@@ -294,7 +294,7 @@ static char **find_locales(void)
if (locale_a == NULL) {
return NULL;
}
- ga_init(&locales_ga, sizeof(char_u *), 20);
+ ga_init(&locales_ga, sizeof(char *), 20);
// Transform locale_a string where each locale is separated by "\n"
// into an array of locale strings.
@@ -308,7 +308,7 @@ static char **find_locales(void)
xfree(locale_a);
// Guarantee that .ga_data is NULL terminated
ga_grow(&locales_ga, 1);
- ((char_u **)locales_ga.ga_data)[locales_ga.ga_len] = NULL;
+ ((char **)locales_ga.ga_data)[locales_ga.ga_len] = NULL;
return locales_ga.ga_data;
}
# endif
diff --git a/src/nvim/lua/converter.c b/src/nvim/lua/converter.c
index 3c129fe7ce..6160b84485 100644
--- a/src/nvim/lua/converter.c
+++ b/src/nvim/lua/converter.c
@@ -391,7 +391,7 @@ nlua_pop_typval_table_processing_end:
case LUA_TFUNCTION: {
LuaRef func = nlua_ref_global(lstate, -1);
- char *name = (char *)register_luafunc(func);
+ char *name = register_luafunc(func);
cur.tv->v_type = VAR_FUNC;
cur.tv->vval.v_string = xstrdup(name);
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 12ddbd094f..1415ceeaed 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -49,6 +49,7 @@
#include "nvim/message.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/option_defs.h"
+#include "nvim/os/fileio.h"
#include "nvim/os/os.h"
#include "nvim/path.h"
#include "nvim/pos.h"
@@ -56,7 +57,6 @@
#include "nvim/runtime.h"
#include "nvim/strings.h"
#include "nvim/ui.h"
-#include "nvim/ui_compositor.h"
#include "nvim/undo.h"
#include "nvim/usercmd.h"
#include "nvim/version.h"
@@ -64,6 +64,7 @@
#include "nvim/window.h"
static int in_fast_callback = 0;
+static bool in_script = false;
// Initialized in nlua_init().
static lua_State *global_lstate = NULL;
@@ -133,8 +134,13 @@ static void nlua_error(lua_State *const lstate, const char *const msg)
str = lua_tolstring(lstate, -1, &len);
}
- msg_ext_set_kind("lua_error");
- semsg_multiline(msg, (int)len, str);
+ if (in_script) {
+ os_errmsg(str);
+ os_errmsg("\n");
+ } else {
+ msg_ext_set_kind("lua_error");
+ semsg_multiline(msg, (int)len, str);
+ }
lua_pop(lstate, 1);
}
@@ -534,7 +540,7 @@ int nlua_get_global_ref_count(void)
return nlua_global_refs->ref_count;
}
-static void nlua_common_vim_init(lua_State *lstate, bool is_thread)
+static void nlua_common_vim_init(lua_State *lstate, bool is_thread, bool is_standalone)
FUNC_ATTR_NONNULL_ARG(1)
{
nlua_ref_state_t *ref_state = nlua_new_ref_state(lstate, is_thread);
@@ -567,7 +573,9 @@ static void nlua_common_vim_init(lua_State *lstate, bool is_thread)
lua_setfield(lstate, -2, "_empty_dict_mt");
// vim.loop
- if (is_thread) {
+ if (is_standalone) {
+ // do nothing, use libluv like in a standalone interpreter
+ } else if (is_thread) {
luv_set_callback(lstate, nlua_luv_thread_cb_cfpcall);
luv_set_thread(lstate, nlua_luv_thread_cfpcall);
luv_set_cthread(lstate, nlua_luv_thread_cfcpcall);
@@ -606,7 +614,7 @@ static int nlua_module_preloader(lua_State *lstate)
return 1;
}
-static bool nlua_init_packages(lua_State *lstate)
+static bool nlua_init_packages(lua_State *lstate, bool is_standalone)
FUNC_ATTR_NONNULL_ALL
{
// put builtin packages in preload
@@ -618,7 +626,7 @@ static bool nlua_init_packages(lua_State *lstate)
lua_pushcclosure(lstate, nlua_module_preloader, 1); // [package, preload, cclosure]
lua_setfield(lstate, -2, def.name); // [package, preload]
- if (nlua_disable_preload && strequal(def.name, "vim.inspect")) {
+ if ((nlua_disable_preload && !is_standalone) && strequal(def.name, "vim.inspect")) {
break;
}
}
@@ -769,7 +777,7 @@ static bool nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
lua_pushcfunction(lstate, &nlua_ui_detach);
lua_setfield(lstate, -2, "ui_detach");
- nlua_common_vim_init(lstate, false);
+ nlua_common_vim_init(lstate, false, false);
// patch require() (only for --startuptime)
if (time_fd != NULL) {
@@ -788,7 +796,7 @@ static bool nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
lua_setglobal(lstate, "vim");
- if (!nlua_init_packages(lstate)) {
+ if (!nlua_init_packages(lstate, false)) {
return false;
}
@@ -813,6 +821,9 @@ void nlua_init(char **argv, int argc, int lua_arg0)
luaL_openlibs(lstate);
if (!nlua_state_init(lstate)) {
os_errmsg(_("E970: Failed to initialize builtin lua modules\n"));
+#ifdef EXITFREE
+ nlua_common_free_all_mem(lstate);
+#endif
os_exit(1);
}
@@ -824,9 +835,28 @@ void nlua_init(char **argv, int argc, int lua_arg0)
static lua_State *nlua_thread_acquire_vm(void)
{
+ return nlua_init_state(true);
+}
+
+void nlua_run_script(char **argv, int argc, int lua_arg0)
+ FUNC_ATTR_NORETURN
+{
+ in_script = true;
+ global_lstate = nlua_init_state(false);
+ luv_set_thread_cb(nlua_thread_acquire_vm, nlua_common_free_all_mem);
+ nlua_init_argv(global_lstate, argv, argc, lua_arg0);
+ bool lua_ok = nlua_exec_file(argv[lua_arg0 - 1]);
+#ifdef EXITFREE
+ nlua_free_all_mem();
+#endif
+ exit(lua_ok ? 0 : 1);
+}
+
+lua_State *nlua_init_state(bool thread)
+{
// If it is called from the main thread, it will attempt to rebuild the cache.
const uv_thread_t self = uv_thread_self();
- if (uv_thread_equal(&main_thread, &self)) {
+ if (!in_script && uv_thread_equal(&main_thread, &self)) {
runtime_search_path_validate();
}
@@ -835,9 +865,11 @@ static lua_State *nlua_thread_acquire_vm(void)
// Add in the lua standard libraries
luaL_openlibs(lstate);
- // print
- lua_pushcfunction(lstate, &nlua_print);
- lua_setglobal(lstate, "print");
+ if (!in_script) {
+ // print
+ lua_pushcfunction(lstate, &nlua_print);
+ lua_setglobal(lstate, "print");
+ }
lua_pushinteger(lstate, 0);
lua_setfield(lstate, LUA_REGISTRYINDEX, "nlua.refcount");
@@ -845,18 +877,20 @@ static lua_State *nlua_thread_acquire_vm(void)
// vim
lua_newtable(lstate);
- nlua_common_vim_init(lstate, true);
+ nlua_common_vim_init(lstate, thread, in_script);
nlua_state_add_stdlib(lstate, true);
- lua_createtable(lstate, 0, 0);
- lua_pushcfunction(lstate, nlua_thr_api_nvim__get_runtime);
- lua_setfield(lstate, -2, "nvim__get_runtime");
- lua_setfield(lstate, -2, "api");
+ if (!in_script) {
+ lua_createtable(lstate, 0, 0);
+ lua_pushcfunction(lstate, nlua_thr_api_nvim__get_runtime);
+ lua_setfield(lstate, -2, "nvim__get_runtime");
+ lua_setfield(lstate, -2, "api");
+ }
lua_setglobal(lstate, "vim");
- nlua_init_packages(lstate);
+ nlua_init_packages(lstate, in_script);
lua_getglobal(lstate, "package");
lua_getfield(lstate, -1, "loaded");
@@ -1440,11 +1474,11 @@ int nlua_source_using_linegetter(LineGetter fgetline, void *cookie, char *name)
estack_push(ETYPE_SCRIPT, name, 0);
garray_T ga;
- char_u *line = NULL;
+ char *line = NULL;
- ga_init(&ga, (int)sizeof(char_u *), 10);
- while ((line = (char_u *)fgetline(0, cookie, 0, false)) != NULL) {
- GA_APPEND(char_u *, &ga, line);
+ ga_init(&ga, (int)sizeof(char *), 10);
+ while ((line = fgetline(0, cookie, 0, false)) != NULL) {
+ GA_APPEND(char *, &ga, line);
}
char *code = ga_concat_strings_sep(&ga, "\n");
size_t len = strlen(code);
@@ -1877,7 +1911,7 @@ int nlua_expand_pat(expand_T *xp, char *pat, int *num_results, char ***results)
goto cleanup_array;
}
- GA_APPEND(char_u *, &result_array, (char_u *)string_to_cstr(v.data.string));
+ GA_APPEND(char *, &result_array, string_to_cstr(v.data.string));
}
xp->xp_pattern += prefix_len;
@@ -1914,7 +1948,7 @@ bool nlua_is_table_from_lua(const typval_T *const arg)
}
}
-char_u *nlua_register_table_as_callable(const typval_T *const arg)
+char *nlua_register_table_as_callable(const typval_T *const arg)
{
LuaRef table_ref = LUA_NOREF;
if (arg->v_type == VAR_DICT) {
@@ -1950,7 +1984,7 @@ char_u *nlua_register_table_as_callable(const typval_T *const arg)
LuaRef func = nlua_ref_global(lstate, -1);
- char_u *name = register_luafunc(func);
+ char *name = register_luafunc(func);
lua_pop(lstate, 1); // []
assert(top == lua_gettop(lstate));
@@ -1960,8 +1994,8 @@ char_u *nlua_register_table_as_callable(const typval_T *const arg)
void nlua_execute_on_key(int c)
{
- char_u buf[NUMBUFLEN];
- size_t buf_len = special_to_buf(c, mod_mask, false, buf);
+ char buf[NUMBUFLEN];
+ size_t buf_len = special_to_buf(c, mod_mask, false, (char_u *)buf);
lua_State *const lstate = global_lstate;
@@ -1977,7 +2011,7 @@ void nlua_execute_on_key(int c)
luaL_checktype(lstate, -1, LUA_TFUNCTION);
// [ vim, vim._on_key, buf ]
- lua_pushlstring(lstate, (const char *)buf, buf_len);
+ lua_pushlstring(lstate, buf, buf_len);
int save_got_int = got_int;
got_int = false; // avoid interrupts when the key typed is Ctrl-C
diff --git a/src/nvim/lua/spell.c b/src/nvim/lua/spell.c
index 0a566b2f86..d510d25e90 100644
--- a/src/nvim/lua/spell.c
+++ b/src/nvim/lua/spell.c
@@ -61,7 +61,7 @@ int nlua_spell_check(lua_State *lstate)
while (*str != NUL) {
attr = HLF_COUNT;
- len = spell_check(curwin, (char_u *)str, &attr, &capcol, false);
+ len = spell_check(curwin, (char *)str, &attr, &capcol, false);
assert(len <= INT_MAX);
if (attr != HLF_COUNT) {
diff --git a/src/nvim/lua/stdlib.c b/src/nvim/lua/stdlib.c
index dac96790d7..6ebca6d97e 100644
--- a/src/nvim/lua/stdlib.c
+++ b/src/nvim/lua/stdlib.c
@@ -40,17 +40,17 @@
# include "lua/stdlib.c.generated.h"
#endif
-static int regex_match(lua_State *lstate, regprog_T **prog, char_u *str)
+static int regex_match(lua_State *lstate, regprog_T **prog, char *str)
{
regmatch_T rm;
rm.regprog = *prog;
rm.rm_ic = false;
- bool match = vim_regexec(&rm, (char *)str, 0);
+ bool match = vim_regexec(&rm, str, 0);
*prog = rm.regprog;
if (match) {
- lua_pushinteger(lstate, (lua_Integer)(rm.startp[0] - (char *)str));
- lua_pushinteger(lstate, (lua_Integer)(rm.endp[0] - (char *)str));
+ lua_pushinteger(lstate, (lua_Integer)(rm.startp[0] - str));
+ lua_pushinteger(lstate, (lua_Integer)(rm.endp[0] - str));
return 2;
}
return 0;
@@ -60,7 +60,7 @@ static int regex_match_str(lua_State *lstate)
{
regprog_T **prog = regex_check(lstate);
const char *str = luaL_checkstring(lstate, 2);
- int nret = regex_match(lstate, prog, (char_u *)str);
+ int nret = regex_match(lstate, prog, (char *)str);
if (!*prog) {
return luaL_error(lstate, "regex: internal error");
@@ -116,7 +116,7 @@ static int regex_match_line(lua_State *lstate)
line[end] = NUL;
}
- int nret = regex_match(lstate, prog, (char_u *)line + start);
+ int nret = regex_match(lstate, prog, line + start);
if (end >= 0) {
line[end] = save;
@@ -198,7 +198,7 @@ static int nlua_str_utf_pos(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
size_t idx = 1;
size_t clen;
for (size_t i = 0; i < s1_len && s1[i] != NUL; i += clen) {
- clen = (size_t)utf_ptr2len_len((const char_u *)(s1) + i, (int)(s1_len - i));
+ clen = (size_t)utf_ptr2len_len(s1 + i, (int)(s1_len - i));
lua_pushinteger(lstate, (long)i + 1);
lua_rawseti(lstate, -2, (int)idx);
idx++;
@@ -266,8 +266,7 @@ int nlua_str_byteindex(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
use_utf16 = lua_toboolean(lstate, 3);
}
- ssize_t byteidx = mb_utf_index_to_bytes((const char_u *)s1, s1_len,
- (size_t)idx, use_utf16);
+ ssize_t byteidx = mb_utf_index_to_bytes(s1, s1_len, (size_t)idx, use_utf16);
if (byteidx == -1) {
return luaL_error(lstate, "index out of range");
}
@@ -483,8 +482,6 @@ static int nlua_stricmp(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
return 1;
}
-#if defined(HAVE_ICONV)
-
/// Convert string from one encoding to another
static int nlua_iconv(lua_State *lstate)
{
@@ -503,14 +500,14 @@ static int nlua_iconv(lua_State *lstate)
size_t str_len = 0;
const char *str = lua_tolstring(lstate, 1, &str_len);
- char_u *from = (char_u *)enc_canonize(enc_skip((char *)lua_tolstring(lstate, 2, NULL)));
- char_u *to = (char_u *)enc_canonize(enc_skip((char *)lua_tolstring(lstate, 3, NULL)));
+ char *from = enc_canonize(enc_skip((char *)lua_tolstring(lstate, 2, NULL)));
+ char *to = enc_canonize(enc_skip((char *)lua_tolstring(lstate, 3, NULL)));
vimconv_T vimconv;
vimconv.vc_type = CONV_NONE;
- convert_setup_ext(&vimconv, (char *)from, false, (char *)to, false);
+ convert_setup_ext(&vimconv, from, false, to, false);
- char_u *ret = (char_u *)string_convert(&vimconv, (char *)str, &str_len);
+ char *ret = string_convert(&vimconv, (char *)str, &str_len);
convert_setup(&vimconv, NULL, NULL);
@@ -520,15 +517,13 @@ static int nlua_iconv(lua_State *lstate)
if (ret == NULL) {
lua_pushnil(lstate);
} else {
- lua_pushlstring(lstate, (char *)ret, str_len);
+ lua_pushlstring(lstate, ret, str_len);
xfree(ret);
}
return 1;
}
-#endif
-
void nlua_state_add_stdlib(lua_State *const lstate, bool is_thread)
{
if (!is_thread) {
@@ -575,12 +570,10 @@ void nlua_state_add_stdlib(lua_State *const lstate, bool is_thread)
luaopen_spell(lstate);
lua_setfield(lstate, -2, "spell");
-#if defined(HAVE_ICONV)
// vim.iconv
// depends on p_ambw, p_emoji
lua_pushcfunction(lstate, &nlua_iconv);
lua_setfield(lstate, -2, "iconv");
-#endif
}
// vim.mpack
diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c
index fecf746036..56f4daed1a 100644
--- a/src/nvim/lua/treesitter.c
+++ b/src/nvim/lua/treesitter.c
@@ -182,8 +182,8 @@ int tslua_add_language(lua_State *L)
uv_lib_t lib;
if (uv_dlopen(path, &lib)) {
- snprintf(IObuff, IOSIZE, "Failed to load parser: uv_dlopen: %s",
- uv_dlerror(&lib));
+ snprintf(IObuff, IOSIZE, "Failed to load parser for language '%s': uv_dlopen: %s",
+ lang_name, uv_dlerror(&lib));
uv_dlclose(&lib);
lua_pushstring(L, IObuff);
return lua_error(L);
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 6f14a00949..e26922bf8e 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -10,7 +10,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <time.h>
#include "auto/config.h"
#include "nvim/arglist.h"
@@ -62,7 +61,6 @@
#include "nvim/os/fileio.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
-#include "nvim/os/pty_process.h"
#include "nvim/os/stdpaths_defs.h"
#include "nvim/os/time.h"
#include "nvim/path.h"
@@ -97,7 +95,6 @@
#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/msgpack_rpc/server.h"
#include "nvim/os/signal.h"
-#include "nvim/tui/tui.h"
// values for "window_layout"
enum {
@@ -242,6 +239,14 @@ int main(int argc, char **argv)
argv0 = argv[0];
+ if (argc > 1 && STRICMP(argv[1], "-ll") == 0) {
+ if (argc == 2) {
+ print_mainerr(err_arg_missing, argv[1]);
+ exit(1);
+ }
+ nlua_run_script(argv, argc, 3);
+ }
+
char *fname = NULL; // file name from command line
mparm_T params; // various parameters passed between
// main() and other functions.
@@ -289,7 +294,13 @@ int main(int argc, char **argv)
}
}
- bool use_builtin_ui = (!headless_mode && !embedded_mode && !silent_mode);
+#ifdef MSWIN
+ // on windows we use CONIN special file, thus we don't know this yet.
+ bool has_term = true;
+#else
+ bool has_term = (stdin_isatty || stdout_isatty || stderr_isatty);
+#endif
+ bool use_builtin_ui = (has_term && !headless_mode && !embedded_mode && !silent_mode);
// don't bind the server yet, if we are using builtin ui.
// This will be done when nvim server has been forked from the ui process
@@ -305,7 +316,7 @@ int main(int argc, char **argv)
bool remote_ui = (ui_client_channel_id != 0);
if (use_builtin_ui && !remote_ui) {
- ui_client_forward_stdin = !params.input_isatty;
+ ui_client_forward_stdin = !stdin_isatty;
uint64_t rv = ui_client_start_server(params.argc, params.argv);
if (!rv) {
os_errmsg("Failed to start Nvim server!\n");
@@ -362,8 +373,8 @@ int main(int argc, char **argv)
debug_break_level = params.use_debug_break_level;
// Read ex-commands if invoked with "-es".
- if (!params.input_isatty && !params.input_istext && silent_mode && exmode_active) {
- input_start(STDIN_FILENO);
+ if (!stdin_isatty && !params.input_istext && silent_mode && exmode_active) {
+ input_start();
}
if (ui_client_channel_id) {
@@ -542,7 +553,9 @@ int main(int argc, char **argv)
if (params.diff_mode) {
// set options in each window for "nvim -d".
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- diff_win_options(wp, true);
+ if (!wp->w_arg_idx_invalid) {
+ diff_win_options(wp, true);
+ }
}
}
@@ -579,6 +592,7 @@ int main(int argc, char **argv)
if (use_builtin_ui) {
os_icon_init();
}
+ os_title_save();
#endif
// Adjust default register name for "unnamed" in 'clipboard'. Can only be
@@ -640,8 +654,8 @@ void os_exit(int r)
if (!event_teardown() && r == 0) {
r = 1; // Exit with error if main_loop did not teardown gracefully.
}
- if (input_global_fd() >= 0) {
- stream_set_blocking(input_global_fd(), true); // normalize stream (#2598)
+ if (used_stdin) {
+ stream_set_blocking(STDIN_FILENO, true); // normalize stream (#2598)
}
ILOG("Nvim exit: %d", r);
@@ -760,7 +774,7 @@ void getout(int exitval)
// Apply 'titleold'.
if (p_title && *p_titleold != NUL) {
- ui_call_set_title(cstr_as_string((char *)p_titleold));
+ ui_call_set_title(cstr_as_string(p_titleold));
}
if (garbage_collect_at_exit) {
@@ -770,6 +784,7 @@ void getout(int exitval)
#ifdef MSWIN
// Restore Windows console icon before exiting.
os_icon_set(NULL, NULL);
+ os_title_reset();
#endif
os_exit(exitval);
@@ -786,9 +801,9 @@ void preserve_exit(void)
// Prevent repeated calls into this method.
if (really_exiting) {
- if (input_global_fd() >= 0) {
+ if (used_stdin) {
// normalize stream (#2598)
- stream_set_blocking(input_global_fd(), true);
+ stream_set_blocking(STDIN_FILENO, true);
}
exit(2);
}
@@ -796,6 +811,11 @@ void preserve_exit(void)
really_exiting = true;
// Ignore SIGHUP while we are already exiting. #9274
signal_reject_deadly();
+
+ if (ui_client_channel_id) {
+ os_exit(1);
+ }
+
os_errmsg(IObuff);
os_errmsg("\n");
ui_flush();
@@ -880,7 +900,7 @@ static void remote_request(mparm_T *params, int remote_args, char *server_addr,
os_errmsg("Remote ui failed to start: ");
os_errmsg(connect_error);
os_errmsg("\n");
- exit(1);
+ os_exit(1);
}
ui_client_channel_id = chan;
@@ -964,7 +984,7 @@ static bool edit_stdin(mparm_T *parmp)
bool implicit = !headless_mode
&& !(embedded_mode && stdin_fd <= 0)
&& (!exmode_active || parmp->input_istext)
- && !parmp->input_isatty
+ && !stdin_isatty
&& parmp->scriptin == NULL; // `-s -` was not given.
return parmp->had_stdin_file || implicit;
}
@@ -1450,11 +1470,9 @@ static void init_startuptime(mparm_T *paramp)
static void check_and_set_isatty(mparm_T *paramp)
{
- stdin_isatty
- = paramp->input_isatty = os_isatty(STDIN_FILENO);
- stdout_isatty
- = paramp->output_isatty = os_isatty(STDOUT_FILENO);
- paramp->err_isatty = os_isatty(STDERR_FILENO);
+ stdin_isatty = os_isatty(STDIN_FILENO);
+ stdout_isatty = os_isatty(STDOUT_FILENO);
+ stderr_isatty = os_isatty(STDERR_FILENO);
TIME_MSG("window checked");
}
@@ -1506,7 +1524,7 @@ static void handle_quickfix(mparm_T *paramp)
set_string_option_direct("ef", -1, paramp->use_ef, OPT_FREE, SID_CARG);
}
vim_snprintf(IObuff, IOSIZE, "cfile %s", p_ef);
- if (qf_init(NULL, (char *)p_ef, p_efm, true, IObuff, p_menc) < 0) {
+ if (qf_init(NULL, p_ef, p_efm, true, IObuff, p_menc) < 0) {
msg_putchar('\n');
os_exit(3);
}
@@ -2106,6 +2124,12 @@ static int execute_env(char *env)
static void mainerr(const char *errstr, const char *str)
FUNC_ATTR_NORETURN
{
+ print_mainerr(errstr, str);
+ os_exit(1);
+}
+
+static void print_mainerr(const char *errstr, const char *str)
+{
char *prgname = path_tail(argv0);
signal_stop(); // kill us with CTRL-C here, if you like
@@ -2121,8 +2145,6 @@ static void mainerr(const char *errstr, const char *str)
os_errmsg(_("\nMore info with \""));
os_errmsg(prgname);
os_errmsg(" -h\"\n");
-
- os_exit(1);
}
/// Prints version information for "nvim -v" or "nvim --version".
diff --git a/src/nvim/main.h b/src/nvim/main.h
index 46d7217364..2d54837872 100644
--- a/src/nvim/main.h
+++ b/src/nvim/main.h
@@ -30,10 +30,7 @@ typedef struct {
char *tagname; // tag from -t argument
char *use_ef; // 'errorfile' from -q argument
- bool input_isatty; // stdin is a terminal
bool input_istext; // stdin is text, not executable (-E/-Es)
- bool output_isatty; // stdout is a terminal
- bool err_isatty; // stderr is a terminal
int no_swap_file; // "-n" argument used
int use_debug_break_level;
diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c
index 04a0107fe8..831d1299a8 100644
--- a/src/nvim/mapping.c
+++ b/src/nvim/mapping.c
@@ -5,6 +5,7 @@
#include <assert.h>
#include <inttypes.h>
+#include <lauxlib.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
@@ -17,6 +18,7 @@
#include "nvim/ascii.h"
#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
+#include "nvim/cmdexpand.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
@@ -38,6 +40,7 @@
#include "nvim/pos.h"
#include "nvim/regexp.h"
#include "nvim/runtime.h"
+#include "nvim/search.h"
#include "nvim/strings.h"
#include "nvim/vim.h"
@@ -1196,7 +1199,7 @@ static char_u *translate_mapping(char_u *str, int cpo_flags)
}
if (c) {
- ga_append(&ga, (char)c);
+ ga_append(&ga, (uint8_t)c);
}
}
ga_append(&ga, NUL);
@@ -1267,93 +1270,135 @@ char_u *set_context_in_map_cmd(expand_T *xp, char *cmd, char *arg, bool forceit,
/// Find all mapping/abbreviation names that match regexp "regmatch".
/// For command line expansion of ":[un]map" and ":[un]abbrev" in all modes.
/// @return OK if matches found, FAIL otherwise.
-int ExpandMappings(regmatch_T *regmatch, int *num_file, char ***file)
+int ExpandMappings(char *pat, regmatch_T *regmatch, int *numMatches, char ***matches)
{
- mapblock_T *mp;
- int hash;
- int count;
- int round;
- char *p;
- int i;
-
- *num_file = 0; // return values in case of FAIL
- *file = NULL;
-
- // round == 1: Count the matches.
- // round == 2: Build the array to keep the matches.
- for (round = 1; round <= 2; round++) {
- count = 0;
-
- for (i = 0; i < 7; i++) {
- if (i == 0) {
- p = "<silent>";
- } else if (i == 1) {
- p = "<unique>";
- } else if (i == 2) {
- p = "<script>";
- } else if (i == 3) {
- p = "<expr>";
- } else if (i == 4 && !expand_buffer) {
- p = "<buffer>";
- } else if (i == 5) {
- p = "<nowait>";
- } else if (i == 6) {
- p = "<special>";
- } else {
+ const bool fuzzy = cmdline_fuzzy_complete(pat);
+
+ *numMatches = 0; // return values in case of FAIL
+ *matches = NULL;
+
+ garray_T ga;
+ if (!fuzzy) {
+ ga_init(&ga, sizeof(char *), 3);
+ } else {
+ ga_init(&ga, sizeof(fuzmatch_str_T), 3);
+ }
+
+ // First search in map modifier arguments
+ for (int i = 0; i < 7; i++) {
+ char *p;
+ if (i == 0) {
+ p = "<silent>";
+ } else if (i == 1) {
+ p = "<unique>";
+ } else if (i == 2) {
+ p = "<script>";
+ } else if (i == 3) {
+ p = "<expr>";
+ } else if (i == 4 && !expand_buffer) {
+ p = "<buffer>";
+ } else if (i == 5) {
+ p = "<nowait>";
+ } else if (i == 6) {
+ p = "<special>";
+ } else {
+ continue;
+ }
+
+ bool match;
+ int score = 0;
+ if (!fuzzy) {
+ match = vim_regexec(regmatch, p, (colnr_T)0);
+ } else {
+ score = fuzzy_match_str(p, pat);
+ match = (score != 0);
+ }
+
+ if (!match) {
+ continue;
+ }
+
+ if (fuzzy) {
+ GA_APPEND(fuzmatch_str_T, &ga, ((fuzmatch_str_T){
+ .idx = ga.ga_len,
+ .str = xstrdup(p),
+ .score = score,
+ }));
+ } else {
+ GA_APPEND(char *, &ga, xstrdup(p));
+ }
+ }
+
+ for (int hash = 0; hash < 256; hash++) {
+ mapblock_T *mp;
+ if (expand_isabbrev) {
+ if (hash > 0) { // only one abbrev list
+ break; // for (hash)
+ }
+ mp = first_abbr;
+ } else if (expand_buffer) {
+ mp = curbuf->b_maphash[hash];
+ } else {
+ mp = maphash[hash];
+ }
+ for (; mp; mp = mp->m_next) {
+ if (!(mp->m_mode & expand_mapmodes)) {
continue;
}
- if (vim_regexec(regmatch, p, (colnr_T)0)) {
- if (round == 1) {
- count++;
- } else {
- (*file)[count++] = xstrdup(p);
- }
+ char *p = (char *)translate_mapping((char_u *)mp->m_keys, CPO_TO_CPO_FLAGS);
+ if (p == NULL) {
+ continue;
}
- }
- for (hash = 0; hash < 256; hash++) {
- if (expand_isabbrev) {
- if (hash > 0) { // only one abbrev list
- break; // for (hash)
- }
- mp = first_abbr;
- } else if (expand_buffer) {
- mp = curbuf->b_maphash[hash];
+ bool match;
+ int score = 0;
+ if (!fuzzy) {
+ match = vim_regexec(regmatch, p, (colnr_T)0);
} else {
- mp = maphash[hash];
+ score = fuzzy_match_str(p, pat);
+ match = (score != 0);
}
- for (; mp; mp = mp->m_next) {
- if (mp->m_mode & expand_mapmodes) {
- p = (char *)translate_mapping((char_u *)mp->m_keys, CPO_TO_CPO_FLAGS);
- if (p != NULL && vim_regexec(regmatch, p, (colnr_T)0)) {
- if (round == 1) {
- count++;
- } else {
- (*file)[count++] = p;
- p = NULL;
- }
- }
- xfree(p);
- }
- } // for (mp)
- } // for (hash)
- if (count == 0) { // no match found
- break; // for (round)
- }
+ if (!match) {
+ xfree(p);
+ continue;
+ }
- if (round == 1) {
- *file = xmalloc((size_t)count * sizeof(char *));
- }
- } // for (round)
+ if (fuzzy) {
+ GA_APPEND(fuzmatch_str_T, &ga, ((fuzmatch_str_T){
+ .idx = ga.ga_len,
+ .str = p,
+ .score = score,
+ }));
+ } else {
+ GA_APPEND(char *, &ga, p);
+ }
+ } // for (mp)
+ } // for (hash)
+ if (ga.ga_len == 0) {
+ return FAIL;
+ }
+
+ if (!fuzzy) {
+ *matches = ga.ga_data;
+ *numMatches = ga.ga_len;
+ } else {
+ fuzzymatches_to_strmatches(ga.ga_data, matches, ga.ga_len, false);
+ *numMatches = ga.ga_len;
+ }
+
+ int count = *numMatches;
if (count > 1) {
// Sort the matches
- sort_strings(*file, count);
+ // Fuzzy matching already sorts the matches
+ if (!fuzzy) {
+ sort_strings(*matches, count);
+ }
// Remove multiple entries
- char **ptr1 = *file;
+ char **ptr1 = *matches;
char **ptr2 = ptr1 + 1;
char **ptr3 = ptr1 + count;
@@ -1367,7 +1412,7 @@ int ExpandMappings(regmatch_T *regmatch, int *num_file, char ***file)
}
}
- *num_file = count;
+ *numMatches = count;
return count == 0 ? FAIL : OK;
}
@@ -1806,9 +1851,9 @@ int makemap(FILE *fd, buf_T *buf)
}
if (putc(' ', fd) < 0
- || put_escstr(fd, (char_u *)mp->m_keys, 0) == FAIL
+ || put_escstr(fd, mp->m_keys, 0) == FAIL
|| putc(' ', fd) < 0
- || put_escstr(fd, (char_u *)mp->m_str, 1) == FAIL
+ || put_escstr(fd, mp->m_str, 1) == FAIL
|| put_eol(fd) < 0) {
return FAIL;
}
@@ -1834,9 +1879,9 @@ int makemap(FILE *fd, buf_T *buf)
// "what": 0 for :map lhs, 1 for :map rhs, 2 for :set
//
// return FAIL for failure, OK otherwise
-int put_escstr(FILE *fd, char_u *strstart, int what)
+int put_escstr(FILE *fd, char *strstart, int what)
{
- char_u *str = strstart;
+ char_u *str = (char_u *)strstart;
int c;
// :map xx <Nop>
@@ -1913,7 +1958,7 @@ int put_escstr(FILE *fd, char_u *strstart, int what)
}
} else if (c < ' ' || c > '~' || c == '|'
|| (what == 0 && c == ' ')
- || (what == 1 && str == strstart && c == ' ')
+ || (what == 1 && str == (char_u *)strstart && c == ' ')
|| (what != 2 && c == '<')) {
if (putc(Ctrl_V, fd) < 0) {
return FAIL;
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index b98935e93d..f1a1f25e6c 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -5,6 +5,7 @@
#include <assert.h>
#include <limits.h>
+#include <stdint.h>
#include <stdio.h>
#include <string.h>
@@ -39,7 +40,6 @@
#include "nvim/sign.h"
#include "nvim/strings.h"
#include "nvim/textobject.h"
-#include "nvim/types.h"
#include "nvim/undo_defs.h"
#include "nvim/vim.h"
@@ -1380,18 +1380,21 @@ void mark_col_adjust(linenr_T lnum, colnr_T mincol, linenr_T lnum_amount, long c
// When deleting lines, this may create duplicate marks in the
// jumplist. They will be removed here for the specified window.
-// When "checktail" is true, removes tail jump if it matches current position.
-void cleanup_jumplist(win_T *wp, bool checktail)
+// When "loadfiles" is true first ensure entries have the "fnum" field set
+// (this may be a bit slow).
+void cleanup_jumplist(win_T *wp, bool loadfiles)
{
int i;
- // Load all the files from the jump list. This is
- // needed to properly clean up duplicate entries, but will take some
- // time.
- for (i = 0; i < wp->w_jumplistlen; i++) {
- if ((wp->w_jumplist[i].fmark.fnum == 0)
- && (wp->w_jumplist[i].fmark.mark.lnum != 0)) {
- fname2fnum(&wp->w_jumplist[i]);
+ if (loadfiles) {
+ // If specified, load all the files from the jump list. This is
+ // needed to properly clean up duplicate entries, but will take some
+ // time.
+ for (i = 0; i < wp->w_jumplistlen; i++) {
+ if ((wp->w_jumplist[i].fmark.fnum == 0)
+ && (wp->w_jumplist[i].fmark.mark.lnum != 0)) {
+ fname2fnum(&wp->w_jumplist[i]);
+ }
}
}
@@ -1439,8 +1442,8 @@ void cleanup_jumplist(win_T *wp, bool checktail)
// When pointer is below last jump, remove the jump if it matches the current
// line. This avoids useless/phantom jumps. #9805
- if (checktail && wp->w_jumplistlen
- && wp->w_jumplistidx == wp->w_jumplistlen) {
+ if (loadfiles // otherwise (i.e.: Shada), last entry should be kept
+ && wp->w_jumplistlen && wp->w_jumplistidx == wp->w_jumplistlen) {
const xfmark_T *fm_last = &wp->w_jumplist[wp->w_jumplistlen - 1];
if (fm_last->fmark.fnum == curbuf->b_fnum
&& fm_last->fmark.mark.lnum == wp->w_cursor.lnum) {
diff --git a/src/nvim/marktree.c b/src/nvim/marktree.c
index 2036ddd21d..77ba6e6fa4 100644
--- a/src/nvim/marktree.c
+++ b/src/nvim/marktree.c
@@ -1182,7 +1182,7 @@ static size_t check_node(MarkTree *b, mtnode_t *x, mtpos_t *last, bool *last_rig
assert(x->ptr[i] != x->ptr[j]);
}
}
- } else {
+ } else if (x->n > 0) {
*last = x->key[x->n - 1].pos;
}
return n_keys;
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index 93ac0fccfa..8b50ba719a 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -100,8 +100,8 @@ static char e_list_item_nr_cell_width_invalid[]
= N_("E1112: List item %d cell width invalid");
static char e_overlapping_ranges_for_nr[]
= N_("E1113: Overlapping ranges for 0x%lx");
-static char e_only_values_of_0x100_and_higher_supported[]
- = N_("E1114: Only values of 0x100 and higher supported");
+static char e_only_values_of_0x80_and_higher_supported[]
+ = N_("E1114: Only values of 0x80 and higher supported");
// To speed up BYTELEN(); keep a lookup table to quickly get the length in
// bytes of a UTF-8 character from the first byte of a UTF-8 string. Bytes
@@ -406,9 +406,9 @@ int bomb_size(void)
}
// Remove all BOM from "s" by moving remaining text.
-void remove_bom(char_u *s)
+void remove_bom(char *s)
{
- char *p = (char *)s;
+ char *p = s;
while ((p = strchr(p, 0xef)) != NULL) {
if ((uint8_t)p[1] == 0xbb && (uint8_t)p[2] == 0xbf) {
@@ -482,12 +482,16 @@ static bool intable(const struct interval *table, size_t n_items, int c)
/// gen_unicode_tables.lua, which must be manually invoked as needed.
int utf_char2cells(int c)
{
- if (c >= 0x100) {
+ // Use the value from setcellwidths() at 0x80 and higher, unless the
+ // character is not printable.
+ if (c >= 0x80 && vim_isprintc(c)) {
int n = cw_value(c);
if (n != 0) {
return n;
}
+ }
+ if (c >= 0x100) {
if (!utf_printable(c)) {
return 6; // unprintable, displays <xxxx>
}
@@ -540,7 +544,7 @@ int utf_ptr2cells_len(const char *p, int size)
// Need to convert to a wide character.
if (size > 0 && (uint8_t)(*p) >= 0x80) {
- if (utf_ptr2len_len((char_u *)p, size) < utf8len_tab[(uint8_t)(*p)]) {
+ if (utf_ptr2len_len(p, size) < utf8len_tab[(uint8_t)(*p)]) {
return 1; // truncated
}
c = utf_ptr2char((char *)p);
@@ -566,8 +570,8 @@ size_t mb_string2cells(const char *str)
{
size_t clen = 0;
- for (const char_u *p = (char_u *)str; *p != NUL; p += utfc_ptr2len((char *)p)) {
- clen += (size_t)utf_ptr2cells((char *)p);
+ for (const char *p = str; *p != NUL; p += utfc_ptr2len(p)) {
+ clen += (size_t)utf_ptr2cells(p);
}
return clen;
@@ -584,9 +588,9 @@ size_t mb_string2cells_len(const char *str, size_t size)
{
size_t clen = 0;
- for (const char_u *p = (char_u *)str; *p != NUL && p < (char_u *)str + size;
- p += utfc_ptr2len_len((char *)p, (int)size + (int)(p - (char_u *)str))) {
- clen += (size_t)utf_ptr2cells((char *)p);
+ for (const char *p = str; *p != NUL && p < str + size;
+ p += utfc_ptr2len_len(p, (int)size + (int)(p - str))) {
+ clen += (size_t)utf_ptr2cells(p);
}
return clen;
@@ -699,23 +703,23 @@ static int utf_safe_read_char_adv(const char_u **s, size_t *n)
// Get character at **pp and advance *pp to the next character.
// Note: composing characters are skipped!
-int mb_ptr2char_adv(const char_u **const pp)
+int mb_ptr2char_adv(const char **const pp)
{
int c;
- c = utf_ptr2char((char *)(*pp));
- *pp += utfc_ptr2len((char *)(*pp));
+ c = utf_ptr2char(*pp);
+ *pp += utfc_ptr2len(*pp);
return c;
}
// Get character at **pp and advance *pp to the next character.
// Note: composing characters are returned as separate characters.
-int mb_cptr2char_adv(const char_u **pp)
+int mb_cptr2char_adv(const char **pp)
{
int c;
- c = utf_ptr2char((char *)(*pp));
- *pp += utf_ptr2len((char *)(*pp));
+ c = utf_ptr2char(*pp);
+ *pp += utf_ptr2len(*pp);
return c;
}
@@ -785,7 +789,7 @@ int utfc_ptr2char_len(const char *p, int *pcc, int maxlen)
int i = 0;
- int len = utf_ptr2len_len((char_u *)p, maxlen);
+ int len = utf_ptr2len_len(p, maxlen);
// Is it safe to use utf_ptr2char()?
bool safe = len > 1 && len <= maxlen;
int c = safe ? utf_ptr2char(p) : (uint8_t)(*p);
@@ -793,7 +797,7 @@ int utfc_ptr2char_len(const char *p, int *pcc, int maxlen)
// Only accept a composing char when the first char isn't illegal.
if ((safe || c < 0x80) && len < maxlen && (uint8_t)p[len] >= 0x80) {
for (; i < MAX_MCO; i++) {
- int len_cc = utf_ptr2len_len((char_u *)p + len, maxlen - len);
+ int len_cc = utf_ptr2len_len(p + len, maxlen - len);
safe = len_cc > 1 && len_cc <= maxlen - len;
if (!safe || (pcc[i] = utf_ptr2char(p + len)) < 0x80
|| !(i == 0 ? utf_composinglike(p, p + len) : utf_iscomposing(pcc[i]))) {
@@ -848,13 +852,13 @@ int utf_byte2len(int b)
// Returns 1 for an illegal byte sequence (also in incomplete byte seq.).
// Returns number > "size" for an incomplete byte sequence.
// Never returns zero.
-int utf_ptr2len_len(const char_u *p, int size)
+int utf_ptr2len_len(const char *p, int size)
{
int len;
int i;
int m;
- len = utf8len_tab[*p];
+ len = utf8len_tab[(uint8_t)(*p)];
if (len == 1) {
return 1; // NUL, ascii or illegal lead byte
}
@@ -925,7 +929,7 @@ int utfc_ptr2len_len(const char *p, int size)
}
// Skip over first UTF-8 char, stopping at a NUL byte.
- len = utf_ptr2len_len((char_u *)p, size);
+ len = utf_ptr2len_len(p, size);
// Check for illegal byte and incomplete byte sequence.
if ((len == 1 && (uint8_t)p[0] >= 0x80) || len > size) {
@@ -944,7 +948,7 @@ int utfc_ptr2len_len(const char *p, int size)
// Next character length should not go beyond size to ensure that
// utf_composinglike(...) does not read beyond size.
- len_next_char = utf_ptr2len_len((char_u *)p + len, size - len);
+ len_next_char = utf_ptr2len_len(p + len, size - len);
if (len_next_char > size - len) {
break;
}
@@ -1462,7 +1466,7 @@ void mb_utflen(const char *s, size_t len, size_t *codepoints, size_t *codeunits)
size_t count = 0, extra = 0;
size_t clen;
for (size_t i = 0; i < len; i += clen) {
- clen = (size_t)utf_ptr2len_len((char_u *)s + i, (int)(len - i));
+ clen = (size_t)utf_ptr2len_len(s + i, (int)(len - i));
// NB: gets the byte value of invalid sequence bytes.
// we only care whether the char fits in the BMP or not
int c = (clen > 1) ? utf_ptr2char(s + i) : (uint8_t)s[i];
@@ -1475,7 +1479,7 @@ void mb_utflen(const char *s, size_t len, size_t *codepoints, size_t *codeunits)
*codeunits += count + extra;
}
-ssize_t mb_utf_index_to_bytes(const char_u *s, size_t len, size_t index, bool use_utf16_units)
+ssize_t mb_utf_index_to_bytes(const char *s, size_t len, size_t index, bool use_utf16_units)
FUNC_ATTR_NONNULL_ALL
{
size_t count = 0;
@@ -1487,7 +1491,7 @@ ssize_t mb_utf_index_to_bytes(const char_u *s, size_t len, size_t index, bool us
clen = (size_t)utf_ptr2len_len(s + i, (int)(len - i));
// NB: gets the byte value of invalid sequence bytes.
// we only care whether the char fits in the BMP or not
- int c = (clen > 1) ? utf_ptr2char((char *)s + i) : s[i];
+ int c = (clen > 1) ? utf_ptr2char(s + i) : (uint8_t)s[i];
count++;
if (use_utf16_units && c > 0xFFFF) {
count++;
@@ -1534,14 +1538,14 @@ void show_utf8(void)
{
int len;
int rlen = 0;
- char_u *line;
+ char *line;
int clen;
int i;
// Get the byte length of the char under the cursor, including composing
// characters.
- line = (char_u *)get_cursor_pos_ptr();
- len = utfc_ptr2len((char *)line);
+ line = get_cursor_pos_ptr();
+ len = utfc_ptr2len(line);
if (len == 0) {
msg("NUL");
return;
@@ -1555,10 +1559,10 @@ void show_utf8(void)
STRCPY(IObuff + rlen, "+ ");
rlen += 2;
}
- clen = utf_ptr2len((char *)line + i);
+ clen = utf_ptr2len(line + i);
}
sprintf(IObuff + rlen, "%02x ", // NOLINT(runtime/printf)
- (line[i] == NL) ? NUL : line[i]); // NUL is stored as NL
+ (line[i] == NL) ? NUL : (uint8_t)line[i]); // NUL is stored as NL
clen--;
rlen += (int)strlen(IObuff + rlen);
if (rlen > IOSIZE - 20) {
@@ -1787,7 +1791,7 @@ void mb_copy_char(const char **const fp, char **const tp)
/// Return the offset from "p_in" to the first byte of a character. When "p_in" is
/// at the start of a character 0 is returned, otherwise the offset to the next
/// character. Can start anywhere in a stream of bytes.
-int mb_off_next(const char_u *base, const char *p_in)
+int mb_off_next(const char *base, const char *p_in)
{
const uint8_t *p = (uint8_t *)p_in;
int i;
@@ -1801,7 +1805,7 @@ int mb_off_next(const char_u *base, const char *p_in)
for (i = 0; (p[i] & 0xc0) == 0x80; i++) {}
if (i > 0) {
// Check for illegal sequence.
- for (j = 0; p - j > base; j++) {
+ for (j = 0; p - j > (uint8_t *)base; j++) {
if ((p[-j] & 0xc0) != 0x80) {
break;
}
@@ -1884,7 +1888,7 @@ void utf_find_illegal(void)
char *p;
int len;
vimconv_T vimconv;
- char_u *tofree = NULL;
+ char *tofree = NULL;
vimconv.vc_type = CONV_NONE;
if (enc_canon_props(curbuf->b_p_fenc) & ENC_8BIT) {
@@ -1899,11 +1903,11 @@ void utf_find_illegal(void)
p = get_cursor_pos_ptr();
if (vimconv.vc_type != CONV_NONE) {
xfree(tofree);
- tofree = (char_u *)string_convert(&vimconv, p, NULL);
+ tofree = string_convert(&vimconv, p, NULL);
if (tofree == NULL) {
break;
}
- p = (char *)tofree;
+ p = tofree;
}
while (*p != NUL) {
@@ -1916,7 +1920,7 @@ void utf_find_illegal(void)
} else {
int l;
- len = (int)(p - (char *)tofree);
+ len = (int)(p - tofree);
for (p = get_cursor_pos_ptr(); *p != NUL && len-- > 0; p += l) {
l = utf_ptr2len(p);
curwin->w_cursor.col += l;
@@ -2024,7 +2028,7 @@ char *mb_prevptr(char *line, char *p)
/// following composing characters) counts as one.
int mb_charlen(const char *str)
{
- const char_u *p = (char_u *)str;
+ const char *p = str;
int count;
if (p == NULL) {
@@ -2032,20 +2036,20 @@ int mb_charlen(const char *str)
}
for (count = 0; *p != NUL; count++) {
- p += utfc_ptr2len((char *)p);
+ p += utfc_ptr2len(p);
}
return count;
}
/// Like mb_charlen() but for a string with specified length.
-int mb_charlen_len(const char_u *str, int len)
+int mb_charlen_len(const char *str, int len)
{
- const char_u *p = str;
+ const char *p = str;
int count;
for (count = 0; *p != NUL && p < str + len; count++) {
- p += utfc_ptr2len((char *)p);
+ p += utfc_ptr2len(p);
}
return count;
@@ -2196,7 +2200,7 @@ static int enc_alias_search(const char *name)
// Get the canonicalized encoding of the current locale.
// Returns an allocated string when successful, NULL when not.
-char_u *enc_locale(void)
+char *enc_locale(void)
{
int i;
char buf[50];
@@ -2232,7 +2236,7 @@ char_u *enc_locale(void)
const char *p = vim_strchr(s, '.');
if (p != NULL) {
if (p > s + 2 && !STRNICMP(p + 1, "EUC", 3)
- && !isalnum((int)p[4]) && p[4] != '-' && p[-3] == '_') {
+ && !isalnum((uint8_t)p[4]) && p[4] != '-' && p[-3] == '_') {
// Copy "XY.EUC" to "euc-XY" to buf[10].
memmove(buf, "euc-", 4);
buf[4] = (char)(ASCII_ISALNUM(p[-2]) ? TOLOWER_ASC(p[-2]) : 0);
@@ -2256,20 +2260,18 @@ enc_locale_copy_enc:
buf[i] = NUL;
}
- return (char_u *)enc_canonize(buf);
+ return enc_canonize(buf);
}
-#if defined(HAVE_ICONV)
-
// Call iconv_open() with a check if iconv() works properly (there are broken
// versions).
// Returns (void *)-1 if failed.
// (should return iconv_t, but that causes problems with prototypes).
-void *my_iconv_open(char_u *to, char_u *from)
+void *my_iconv_open(char *to, char *from)
{
iconv_t fd;
-# define ICONV_TESTLEN 400
- char_u tobuf[ICONV_TESTLEN];
+#define ICONV_TESTLEN 400
+ char tobuf[ICONV_TESTLEN];
char *p;
size_t tolen;
static WorkingStatus iconv_working = kUnknown;
@@ -2277,7 +2279,7 @@ void *my_iconv_open(char_u *to, char_u *from)
if (iconv_working == kBroken) {
return (void *)-1; // detected a broken iconv() previously
}
- fd = iconv_open(enc_skip((char *)to), enc_skip((char *)from));
+ fd = iconv_open(enc_skip(to), enc_skip(from));
if (fd != (iconv_t)-1 && iconv_working == kUnknown) {
// Do a dummy iconv() call to check if it actually works. There is a
@@ -2285,7 +2287,7 @@ void *my_iconv_open(char_u *to, char_u *from)
// because it's wide-spread. The symptoms are that after outputting
// the initial shift state the "to" pointer is NULL and conversion
// stops for no apparent reason after about 8160 characters.
- p = (char *)tobuf;
+ p = tobuf;
tolen = ICONV_TESTLEN;
(void)iconv(fd, NULL, NULL, &p, &tolen);
if (p == NULL) {
@@ -2305,8 +2307,8 @@ void *my_iconv_open(char_u *to, char_u *from)
// sequence and set "*unconvlenp" to the length of it.
// Returns the converted string in allocated memory. NULL for an error.
// If resultlenp is not NULL, sets it to the result length in bytes.
-static char_u *iconv_string(const vimconv_T *const vcp, const char_u *str, size_t slen,
- size_t *unconvlenp, size_t *resultlenp)
+static char *iconv_string(const vimconv_T *const vcp, const char *str, size_t slen,
+ size_t *unconvlenp, size_t *resultlenp)
{
const char *from;
size_t fromlen;
@@ -2314,11 +2316,11 @@ static char_u *iconv_string(const vimconv_T *const vcp, const char_u *str, size_
size_t tolen;
size_t len = 0;
size_t done = 0;
- char_u *result = NULL;
- char_u *p;
+ char *result = NULL;
+ char *p;
int l;
- from = (char *)str;
+ from = str;
fromlen = slen;
for (;;) {
if (len == 0 || ICONV_ERRNO == ICONV_E2BIG) {
@@ -2333,7 +2335,7 @@ static char_u *iconv_string(const vimconv_T *const vcp, const char_u *str, size_
result = p;
}
- to = (char *)result + done;
+ to = result + done;
tolen = len - done - 2;
// Avoid a warning for systems with a wrong iconv() prototype by
// casting the second argument to void *.
@@ -2373,17 +2375,15 @@ static char_u *iconv_string(const vimconv_T *const vcp, const char_u *str, size_
break;
}
// Not enough room or skipping illegal sequence.
- done = (size_t)(to - (char *)result);
+ done = (size_t)(to - result);
}
if (resultlenp != NULL && result != NULL) {
- *resultlenp = (size_t)(to - (char *)result);
+ *resultlenp = (size_t)(to - result);
}
return result;
}
-#endif // HAVE_ICONV
-
/// Setup "vcp" for conversion from "from" to "to".
/// The names must have been made canonical with enc_canonize().
/// vcp->vc_type must have been initialized to CONV_NONE.
@@ -2408,11 +2408,9 @@ int convert_setup_ext(vimconv_T *vcp, char *from, bool from_unicode_is_utf8, cha
int to_is_utf8;
// Reset to no conversion.
-#ifdef HAVE_ICONV
if (vcp->vc_type == CONV_ICONV && vcp->vc_fd != (iconv_t)-1) {
iconv_close(vcp->vc_fd);
}
-#endif
*vcp = (vimconv_T)MBYTE_NONE_CONV;
// No conversion when one of the names is empty or they are equal.
@@ -2448,18 +2446,15 @@ int convert_setup_ext(vimconv_T *vcp, char *from, bool from_unicode_is_utf8, cha
} else if (from_is_utf8 && (to_prop & ENC_LATIN9)) {
// Internal utf-8 -> latin9 conversion.
vcp->vc_type = CONV_TO_LATIN9;
- }
-#ifdef HAVE_ICONV
- else { // NOLINT(readability/braces)
+ } else {
// Use iconv() for conversion.
- vcp->vc_fd = (iconv_t)my_iconv_open(to_is_utf8 ? (char_u *)"utf-8" : (char_u *)to,
- from_is_utf8 ? (char_u *)"utf-8" : (char_u *)from);
+ vcp->vc_fd = (iconv_t)my_iconv_open(to_is_utf8 ? "utf-8" : to,
+ from_is_utf8 ? "utf-8" : from);
if (vcp->vc_fd != (iconv_t)-1) {
vcp->vc_type = CONV_ICONV;
vcp->vc_factor = 4; // could be longer too...
}
}
-#endif
if (vcp->vc_type == CONV_NONE) {
return FAIL;
}
@@ -2474,14 +2469,13 @@ int convert_setup_ext(vimconv_T *vcp, char *from, bool from_unicode_is_utf8, cha
/// When something goes wrong, NULL is returned and "*lenp" is unchanged.
char *string_convert(const vimconv_T *const vcp, char *ptr, size_t *lenp)
{
- return (char *)string_convert_ext(vcp, (char_u *)ptr, lenp, NULL);
+ return string_convert_ext(vcp, ptr, lenp, NULL);
}
// Like string_convert(), but when "unconvlenp" is not NULL and there are is
// an incomplete sequence at the end it is not converted and "*unconvlenp" is
// set to the number of remaining bytes.
-char_u *string_convert_ext(const vimconv_T *const vcp, char_u *ptr, size_t *lenp,
- size_t *unconvlenp)
+char *string_convert_ext(const vimconv_T *const vcp, char *ptr, size_t *lenp, size_t *unconvlenp)
{
char_u *retval = NULL;
char_u *d;
@@ -2490,12 +2484,12 @@ char_u *string_convert_ext(const vimconv_T *const vcp, char_u *ptr, size_t *lenp
size_t len;
if (lenp == NULL) {
- len = strlen((char *)ptr);
+ len = strlen(ptr);
} else {
len = *lenp;
}
if (len == 0) {
- return (char_u *)xstrdup("");
+ return xstrdup("");
}
switch (vcp->vc_type) {
@@ -2503,7 +2497,7 @@ char_u *string_convert_ext(const vimconv_T *const vcp, char_u *ptr, size_t *lenp
retval = xmalloc(len * 2 + 1);
d = retval;
for (size_t i = 0; i < len; i++) {
- c = ptr[i];
+ c = (uint8_t)ptr[i];
if (c < 0x80) {
*d++ = (char_u)c;
} else {
@@ -2521,7 +2515,7 @@ char_u *string_convert_ext(const vimconv_T *const vcp, char_u *ptr, size_t *lenp
retval = xmalloc(len * 3 + 1);
d = retval;
for (size_t i = 0; i < len; i++) {
- c = ptr[i];
+ c = (uint8_t)ptr[i];
switch (c) {
case 0xa4:
c = 0x20ac; break; // euro
@@ -2557,7 +2551,7 @@ char_u *string_convert_ext(const vimconv_T *const vcp, char_u *ptr, size_t *lenp
if (l == 0) {
*d++ = NUL;
} else if (l == 1) {
- uint8_t l_w = utf8len_tab_zero[ptr[i]];
+ uint8_t l_w = utf8len_tab_zero[(uint8_t)ptr[i]];
if (l_w == 0) {
// Illegal utf-8 byte cannot be converted
@@ -2569,9 +2563,9 @@ char_u *string_convert_ext(const vimconv_T *const vcp, char_u *ptr, size_t *lenp
*unconvlenp = len - i;
break;
}
- *d++ = ptr[i];
+ *d++ = (uint8_t)ptr[i];
} else {
- c = utf_ptr2char((char *)ptr + i);
+ c = utf_ptr2char(ptr + i);
if (vcp->vc_type == CONV_TO_LATIN9) {
switch (c) {
case 0x20ac:
@@ -2623,14 +2617,12 @@ char_u *string_convert_ext(const vimconv_T *const vcp, char_u *ptr, size_t *lenp
}
break;
-#ifdef HAVE_ICONV
case CONV_ICONV: // conversion with vcp->vc_fd
- retval = iconv_string(vcp, ptr, len, unconvlenp, lenp);
+ retval = (char_u *)iconv_string(vcp, ptr, len, unconvlenp, lenp);
break;
-#endif
}
- return retval;
+ return (char *)retval;
}
/// Table set by setcellwidths().
@@ -2709,7 +2701,7 @@ void f_setcellwidths(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (li_tv->v_type != VAR_LIST || li_tv->vval.v_list == NULL) {
semsg(_(e_list_item_nr_is_not_list), item);
- xfree(ptrs);
+ xfree((void *)ptrs);
return;
}
@@ -2725,25 +2717,25 @@ void f_setcellwidths(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
if (i == 0) {
n1 = lili_tv->vval.v_number;
- if (n1 < 0x100) {
- emsg(_(e_only_values_of_0x100_and_higher_supported));
- xfree(ptrs);
+ if (n1 < 0x80) {
+ emsg(_(e_only_values_of_0x80_and_higher_supported));
+ xfree((void *)ptrs);
return;
}
} else if (i == 1 && lili_tv->vval.v_number < n1) {
semsg(_(e_list_item_nr_range_invalid), item);
- xfree(ptrs);
+ xfree((void *)ptrs);
return;
} else if (i == 2 && (lili_tv->vval.v_number < 1 || lili_tv->vval.v_number > 2)) {
semsg(_(e_list_item_nr_cell_width_invalid), item);
- xfree(ptrs);
+ xfree((void *)ptrs);
return;
}
}
if (i != 3) {
semsg(_(e_list_item_nr_does_not_contain_3_numbers), item);
- xfree(ptrs);
+ xfree((void *)ptrs);
return;
}
@@ -2762,7 +2754,7 @@ void f_setcellwidths(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
const varnumber_T n1 = TV_LIST_ITEM_TV(lili)->vval.v_number;
if (item > 0 && n1 <= table[item - 1].last) {
semsg(_(e_overlapping_ranges_for_nr), (long)n1);
- xfree(ptrs);
+ xfree((void *)ptrs);
xfree(table);
return;
}
@@ -2773,7 +2765,7 @@ void f_setcellwidths(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
table[item].width = (char)TV_LIST_ITEM_TV(lili)->vval.v_number;
}
- xfree(ptrs);
+ xfree((void *)ptrs);
cw_interval_T *const cw_table_save = cw_table;
const size_t cw_table_size_save = cw_table_size;
@@ -2795,6 +2787,21 @@ void f_setcellwidths(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
redraw_all_later(UPD_NOT_VALID);
}
+/// "getcellwidths()" function
+void f_getcellwidths(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
+{
+ tv_list_alloc_ret(rettv, (ptrdiff_t)cw_table_size);
+
+ for (size_t i = 0; i < cw_table_size; i++) {
+ list_T *entry = tv_list_alloc(3);
+ tv_list_append_number(entry, (varnumber_T)cw_table[i].first);
+ tv_list_append_number(entry, (varnumber_T)cw_table[i].last);
+ tv_list_append_number(entry, (varnumber_T)cw_table[i].width);
+
+ tv_list_append_list(rettv->vval.v_list, entry);
+ }
+}
+
void f_charclass(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
if (tv_check_for_string_arg(argvars, 0) == FAIL
diff --git a/src/nvim/mbyte_defs.h b/src/nvim/mbyte_defs.h
index 53b01a211f..e913e20f9f 100644
--- a/src/nvim/mbyte_defs.h
+++ b/src/nvim/mbyte_defs.h
@@ -46,9 +46,7 @@ typedef enum {
typedef struct {
int vc_type; ///< Zero or more ConvFlags.
int vc_factor; ///< Maximal expansion factor.
-#ifdef HAVE_ICONV
iconv_t vc_fd; ///< Value for CONV_ICONV.
-#endif
bool vc_fail; ///< What to do with invalid characters: if true, fail,
///< otherwise use '?'.
} vimconv_T;
diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c
index 61d7893948..46be9ccea5 100644
--- a/src/nvim/memfile.c
+++ b/src/nvim/memfile.c
@@ -62,7 +62,6 @@
#include "nvim/os/os.h"
#include "nvim/path.h"
#include "nvim/pos.h"
-#include "nvim/types.h"
#include "nvim/vim.h"
#define MEMFILE_PAGE_SIZE 4096 /// default page size
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index eee3b9d517..b3fc64a68c 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -149,7 +149,7 @@ struct data_block {
#define DB_INDEX_MASK (~DB_MARKED)
#define INDEX_SIZE (sizeof(unsigned)) // size of one db_index entry
-#define HEADER_SIZE (sizeof(DATA_BL) - INDEX_SIZE) // size of data block header
+#define HEADER_SIZE (offsetof(DATA_BL, db_index)) // size of data block header
enum {
B0_FNAME_SIZE_ORG = 900, // what it was in older versions
@@ -749,7 +749,7 @@ void ml_recover(bool checkext)
int len = (int)strlen(fname);
if (checkext && len >= 4
&& STRNICMP(fname + len - 4, ".s", 2) == 0
- && vim_strchr("abcdefghijklmnopqrstuvw", TOLOWER_ASC(fname[len - 2])) != NULL
+ && vim_strchr("abcdefghijklmnopqrstuvw", TOLOWER_ASC((uint8_t)fname[len - 2])) != NULL
&& ASCII_ISALPHA(fname[len - 1])) {
directly = true;
fname_used = xstrdup(fname); // make a copy for mf_open()
@@ -757,7 +757,7 @@ void ml_recover(bool checkext)
directly = false;
// count the number of matching swap files
- len = recover_names((char_u *)fname, false, 0, NULL);
+ len = recover_names(fname, false, 0, NULL);
if (len == 0) { // no swap files found
semsg(_("E305: No swap file found for %s"), fname);
goto theend;
@@ -767,7 +767,7 @@ void ml_recover(bool checkext)
i = 1;
} else { // several swap files found, choose
// list the names of the swap files
- (void)recover_names((char_u *)fname, true, 0, NULL);
+ (void)recover_names(fname, true, 0, NULL);
msg_putchar('\n');
msg_puts(_("Enter number of swap file to use (0 to quit): "));
i = get_number(false, NULL);
@@ -776,7 +776,7 @@ void ml_recover(bool checkext)
}
}
// get the swap file name that will be used
- (void)recover_names((char_u *)fname, false, i, &fname_used);
+ (void)recover_names(fname, false, i, &fname_used);
}
if (fname_used == NULL) {
goto theend; // user chose invalid number.
@@ -1201,24 +1201,24 @@ theend:
/// @param list when true, list the swap file names
/// @param nr when non-zero, return nr'th swap file name
/// @param fname_out result when "nr" > 0
-int recover_names(char_u *fname, int list, int nr, char **fname_out)
+int recover_names(char *fname, int list, int nr, char **fname_out)
{
int num_names;
char *(names[6]);
- char_u *tail;
+ char *tail;
char *p;
int file_count = 0;
char **files;
- char_u *fname_res = NULL;
+ char *fname_res = NULL;
#ifdef HAVE_READLINK
- char_u fname_buf[MAXPATHL];
+ char fname_buf[MAXPATHL];
#endif
if (fname != NULL) {
#ifdef HAVE_READLINK
// Expand symlink in the file name, because the swap file is created
// with the actual file instead of with the symlink.
- if (resolve_symlink((char *)fname, (char *)fname_buf) == OK) {
+ if (resolve_symlink(fname, fname_buf) == OK) {
fname_res = fname_buf;
} else
#endif
@@ -1250,7 +1250,7 @@ int recover_names(char_u *fname, int list, int nr, char **fname_out)
names[2] = xstrdup(".sw?");
num_names = 3;
} else {
- num_names = recov_file_names(names, (char *)fname_res, true);
+ num_names = recov_file_names(names, fname_res, true);
}
} else { // check directory dir_name
if (fname == NULL) {
@@ -1267,13 +1267,12 @@ int recover_names(char_u *fname, int list, int nr, char **fname_out)
&& len > 1
&& p[-1] == p[-2]) {
// Ends with '//', Use Full path for swap name
- tail = (char_u *)make_percent_swname(dir_name,
- (char *)fname_res);
+ tail = make_percent_swname(dir_name, fname_res);
} else {
- tail = (char_u *)path_tail((char *)fname_res);
- tail = (char_u *)concat_fnames(dir_name, (char *)tail, true);
+ tail = path_tail(fname_res);
+ tail = concat_fnames(dir_name, tail, true);
}
- num_names = recov_file_names(names, (char *)tail, false);
+ num_names = recov_file_names(names, tail, false);
xfree(tail);
}
}
@@ -1290,11 +1289,11 @@ int recover_names(char_u *fname, int list, int nr, char **fname_out)
// not able to execute the shell).
// Try finding a swap file by simply adding ".swp" to the file name.
if (*dirp == NUL && file_count + num_files == 0 && fname != NULL) {
- char_u *swapname = (char_u *)modname((char *)fname_res, ".swp", true);
+ char *swapname = modname(fname_res, ".swp", true);
if (swapname != NULL) {
- if (os_path_exists((char *)swapname)) {
- files = xmalloc(sizeof(char_u *));
- files[0] = (char *)swapname;
+ if (os_path_exists(swapname)) {
+ files = xmalloc(sizeof(char *));
+ files[0] = swapname;
swapname = NULL;
num_files = 1;
}
@@ -1877,7 +1876,7 @@ int ml_append(linenr_T lnum, char *line, colnr_T len, bool newfile)
/// @param line text of the new line
/// @param len length of new line, including NUL, or 0
/// @param newfile flag, see above
-int ml_append_buf(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, bool newfile)
+int ml_append_buf(buf_T *buf, linenr_T lnum, char *line, colnr_T len, bool newfile)
FUNC_ATTR_NONNULL_ARG(1)
{
if (buf->b_ml.ml_mfp == NULL) {
@@ -1887,7 +1886,7 @@ int ml_append_buf(buf_T *buf, linenr_T lnum, char_u *line, colnr_T len, bool new
if (buf->b_ml.ml_line_lnum != 0) {
ml_flush_line(buf);
}
- return ml_append_int(buf, lnum, (char *)line, len, newfile, false);
+ return ml_append_int(buf, lnum, line, len, newfile, false);
}
/// @param lnum append after this line (can be 0)
@@ -2721,7 +2720,8 @@ static bhdr_T *ml_new_ptr(memfile_T *mfp)
PTR_BL *pp = hp->bh_data;
pp->pb_id = PTR_ID;
pp->pb_count = 0;
- pp->pb_count_max = (uint16_t)((mfp->mf_page_size - sizeof(PTR_BL)) / sizeof(PTR_EN) + 1);
+ pp->pb_count_max
+ = (uint16_t)((mfp->mf_page_size - offsetof(PTR_BL, pb_pointer)) / sizeof(PTR_EN));
return hp;
}
@@ -3000,7 +3000,7 @@ int resolve_symlink(const char *fname, char *buf)
// If it's relative, build a new path based on the directory
// portion of the filename (if any) and the path the symlink
// points to.
- if (path_is_absolute((char_u *)buf)) {
+ if (path_is_absolute(buf)) {
STRCPY(tmp, buf);
} else {
char *tail = path_tail(tmp);
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index aa8314b23d..5356300382 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -31,7 +31,6 @@
#include "nvim/message.h"
#include "nvim/sign.h"
#include "nvim/ui.h"
-#include "nvim/ui_compositor.h"
#include "nvim/usercmd.h"
#include "nvim/vim.h"
diff --git a/src/nvim/menu.c b/src/nvim/menu.c
index 0fa45ac24a..2a18b08d8d 100644
--- a/src/nvim/menu.c
+++ b/src/nvim/menu.c
@@ -6,6 +6,7 @@
#include <assert.h>
#include <stdbool.h>
+#include <stdint.h>
#include <string.h>
#include "nvim/ascii.h"
diff --git a/src/nvim/message.c b/src/nvim/message.c
index de4acd601f..3b3dfcd5b6 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -2514,7 +2514,7 @@ static void store_sb_text(char **sb_str, char *s, int attr, int *sb_col, int fin
}
if (s > *sb_str) {
- mp = xmalloc((sizeof(msgchunk_T) + (size_t)(s - *sb_str)));
+ mp = xmalloc(offsetof(msgchunk_T, sb_text) + (size_t)(s - *sb_str) + 1);
mp->sb_eol = (char)finish;
mp->sb_msg_col = *sb_col;
mp->sb_attr = attr;
@@ -3006,7 +3006,7 @@ static int do_more_prompt(int typed_char)
#if defined(MSWIN)
/// Headless (no UI) error message handler.
-static void do_msg(char *str, bool errmsg)
+static void do_msg(const char *str, bool errmsg)
{
static bool did_err = false;
assert(str != NULL);
@@ -3026,13 +3026,13 @@ static void do_msg(char *str, bool errmsg)
}
}
-void os_errmsg(char *str)
+void os_errmsg(const char *str)
{
do_msg(str, true);
}
/// Headless (no UI) message handler.
-void os_msg(char *str)
+void os_msg(const char *str)
{
do_msg(str, false);
}
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index b7d15fe9af..950b025e53 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -3,6 +3,7 @@
#include <assert.h>
#include <stdbool.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -85,17 +86,17 @@ static int get_mouse_class(char *p)
/// Move "pos" back to the start of the word it's in.
static void find_start_of_word(pos_T *pos)
{
- char_u *line;
+ char *line;
int cclass;
int col;
- line = (char_u *)ml_get(pos->lnum);
- cclass = get_mouse_class((char *)line + pos->col);
+ line = ml_get(pos->lnum);
+ cclass = get_mouse_class(line + pos->col);
while (pos->col > 0) {
col = pos->col - 1;
- col -= utf_head_off((char *)line, (char *)line + col);
- if (get_mouse_class((char *)line + col) != cclass) {
+ col -= utf_head_off(line, line + col);
+ if (get_mouse_class(line + col) != cclass) {
break;
}
pos->col = col;
@@ -106,19 +107,19 @@ static void find_start_of_word(pos_T *pos)
/// When 'selection' is "exclusive", the position is just after the word.
static void find_end_of_word(pos_T *pos)
{
- char_u *line;
+ char *line;
int cclass;
int col;
- line = (char_u *)ml_get(pos->lnum);
+ line = ml_get(pos->lnum);
if (*p_sel == 'e' && pos->col > 0) {
pos->col--;
- pos->col -= utf_head_off((char *)line, (char *)line + pos->col);
+ pos->col -= utf_head_off(line, line + pos->col);
}
- cclass = get_mouse_class((char *)line + pos->col);
+ cclass = get_mouse_class(line + pos->col);
while (line[pos->col] != NUL) {
- col = pos->col + utfc_ptr2len((char *)line + pos->col);
- if (get_mouse_class((char *)line + col) != cclass) {
+ col = pos->col + utfc_ptr2len(line + pos->col);
+ if (get_mouse_class(line + col) != cclass) {
if (*p_sel == 'e') {
pos->col = col;
}
@@ -1539,16 +1540,16 @@ colnr_T vcol2col(win_T *const wp, const linenr_T lnum, const colnr_T vcol)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
// try to advance to the specified column
- char_u *line = (char_u *)ml_get_buf(wp->w_buffer, lnum, false);
+ char *line = ml_get_buf(wp->w_buffer, lnum, false);
chartabsize_T cts;
- init_chartabsize_arg(&cts, wp, lnum, 0, (char *)line, (char *)line);
+ init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
while (cts.cts_vcol < vcol && *cts.cts_ptr != NUL) {
cts.cts_vcol += win_lbr_chartabsize(&cts, NULL);
MB_PTR_ADV(cts.cts_ptr);
}
clear_chartabsize_arg(&cts);
- return (colnr_T)((char_u *)cts.cts_ptr - line);
+ return (colnr_T)(cts.cts_ptr - line);
}
/// Set UI mouse depending on current mode and 'mouse'.
@@ -1574,10 +1575,10 @@ static void set_mouse_topline(win_T *wp)
static colnr_T scroll_line_len(linenr_T lnum)
{
colnr_T col = 0;
- char_u *line = (char_u *)ml_get(lnum);
+ char *line = ml_get(lnum);
if (*line != NUL) {
for (;;) {
- int numchar = win_chartabsize(curwin, (char *)line, col);
+ int numchar = win_chartabsize(curwin, line, col);
MB_PTR_ADV(line);
if (*line == NUL) { // don't count the last character
break;
@@ -1679,10 +1680,10 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
// highlighting the second byte, not the ninth.
linenr_T lnum = wp->w_cursor.lnum;
- char_u *line = (char_u *)ml_get(lnum);
- char_u *ptr = line;
- char_u *ptr_end;
- char_u *ptr_row_offset = line; // Where we begin adjusting `ptr_end`
+ char *line = ml_get(lnum);
+ char *ptr = line;
+ char *ptr_end;
+ char *ptr_row_offset = line; // Where we begin adjusting `ptr_end`
// Find the offset where scanning should begin.
int offset = wp->w_leftcol;
@@ -1700,8 +1701,8 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
// checked for concealed characters.
vcol = 0;
while (vcol < offset && *ptr != NUL) {
- vcol += win_chartabsize(curwin, (char *)ptr, vcol);
- ptr += utfc_ptr2len((char *)ptr);
+ vcol += win_chartabsize(curwin, ptr, vcol);
+ ptr += utfc_ptr2len(ptr);
}
ptr_row_offset = ptr;
@@ -1711,8 +1712,8 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
vcol = offset;
ptr_end = ptr_row_offset;
while (vcol < col && *ptr_end != NUL) {
- vcol += win_chartabsize(curwin, (char *)ptr_end, vcol);
- ptr_end += utfc_ptr2len((char *)ptr_end);
+ vcol += win_chartabsize(curwin, ptr_end, vcol);
+ ptr_end += utfc_ptr2len(ptr_end);
}
int matchid;
@@ -1726,7 +1727,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
#define DECR() nudge--; ptr_end -= utfc_ptr2len((char *)ptr_end)
while (ptr < ptr_end && *ptr != NUL) {
- cwidth = win_chartabsize(curwin, (char *)ptr, vcol);
+ cwidth = win_chartabsize(curwin, ptr, vcol);
vcol += cwidth;
if (cwidth > 1 && *ptr == '\t' && nudge > 0) {
// A tab will "absorb" any previous adjustments.
@@ -1754,7 +1755,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
while (prev_matchid == matchid && *ptr != NUL) {
INCR();
- ptr += utfc_ptr2len((char *)ptr);
+ ptr += utfc_ptr2len(ptr);
matchid = syn_get_concealed_id(wp, lnum, (colnr_T)(ptr - line));
}
@@ -1762,7 +1763,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
}
}
- ptr += utfc_ptr2len((char *)ptr);
+ ptr += utfc_ptr2len(ptr);
}
return col + nudge;
diff --git a/src/nvim/move.c b/src/nvim/move.c
index dc2f4b4844..3af26b910e 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -27,12 +27,14 @@
#include "nvim/eval/window.h"
#include "nvim/fold.h"
#include "nvim/getchar.h"
+#include "nvim/gettext.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/highlight.h"
#include "nvim/macros.h"
#include "nvim/mbyte.h"
#include "nvim/memline_defs.h"
+#include "nvim/message.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/option.h"
@@ -758,7 +760,7 @@ void curs_columns(win_T *wp, int may_scroll)
// When cursor wraps to first char of next line in Insert
// mode, the 'showbreak' string isn't shown, backup to first
// column
- char *const sbr = (char *)get_showbreak_value(wp);
+ char *const sbr = get_showbreak_value(wp);
if (*sbr && *get_cursor_pos_ptr() == NUL
&& wp->w_wcol == vim_strsize(sbr)) {
wp->w_wcol = 0;
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 0c23a7798c..d60e18590f 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -20,14 +20,15 @@
#include "nvim/channel.h"
#include "nvim/event/defs.h"
#include "nvim/event/loop.h"
+#include "nvim/event/process.h"
#include "nvim/event/rstream.h"
#include "nvim/event/stream.h"
#include "nvim/event/wstream.h"
-#include "nvim/globals.h"
#include "nvim/log.h"
#include "nvim/main.h"
#include "nvim/map.h"
#include "nvim/memory.h"
+#include "nvim/message.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/msgpack_rpc/channel_defs.h"
#include "nvim/msgpack_rpc/helpers.h"
diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c
index b1e033d9f1..1d75c208be 100644
--- a/src/nvim/msgpack_rpc/server.c
+++ b/src/nvim/msgpack_rpc/server.c
@@ -101,7 +101,7 @@ char *server_address_new(const char *name)
xfree(dir);
#endif
if ((size_t)r >= sizeof(fmt)) {
- ELOG("truncated server address");
+ ELOG("truncated server address: %.40s...", fmt);
}
return xstrdup(fmt);
}
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 8f4240c062..b88cfb8926 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -451,12 +451,34 @@ static int find_command(int cmdchar)
/// message, return true.
static bool check_text_locked(oparg_T *oap)
{
- if (text_locked()) {
+ if (!text_locked()) {
+ return false;
+ }
+
+ if (oap != NULL) {
clearopbeep(oap);
- text_locked_msg();
+ }
+ text_locked_msg();
+ return true;
+}
+
+/// If text is locked, "curbuf->b_ro_locked" or "allbuf_lock" is set:
+/// Give an error message, possibly beep and return true.
+/// "oap" may be NULL.
+static bool check_text_or_curbuf_locked(oparg_T *oap)
+{
+ if (check_text_locked(oap)) {
return true;
}
- return false;
+
+ if (!curbuf_locked()) {
+ return false;
+ }
+
+ if (oap != NULL) {
+ clearop(oap);
+ }
+ return true;
}
/// Normal state entry point. This is called on:
@@ -1107,8 +1129,7 @@ static int normal_execute(VimState *state, int key)
goto finish;
}
- if ((nv_cmds[s->idx].cmd_flags & NV_NCW)
- && (check_text_locked(&s->oa) || curbuf_locked())) {
+ if ((nv_cmds[s->idx].cmd_flags & NV_NCW) && check_text_or_curbuf_locked(&s->oa)) {
// this command is not allowed now
s->command_finished = true;
goto finish;
@@ -1505,8 +1526,7 @@ void restore_visual_mode(void)
/// @param dir the direction of searching, is either FORWARD or BACKWARD
/// @param *colp is in/decremented if "ptr[-dir]" should also be included.
/// @param bnp points to a counter for square brackets.
-static bool find_is_eval_item(const char_u *const ptr, int *const colp, int *const bnp,
- const int dir)
+static bool find_is_eval_item(const char *const ptr, int *const colp, int *const bnp, const int dir)
{
// Accept everything inside [].
if ((*ptr == ']' && dir == BACKWARD) || (*ptr == '[' && dir == FORWARD)) {
@@ -1614,7 +1634,7 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, char **text
|| (find_type & FIND_IDENT))
&& (!(find_type & FIND_EVAL)
|| prevcol == 0
- || !find_is_eval_item((char_u *)ptr + prevcol, &prevcol, &bn, BACKWARD))) {
+ || !find_is_eval_item(ptr + prevcol, &prevcol, &bn, BACKWARD))) {
break;
}
col = prevcol;
@@ -1657,7 +1677,7 @@ size_t find_ident_at_pos(win_T *wp, linenr_T lnum, colnr_T startcol, char **text
: mb_get_class(ptr + col) != 0)
|| ((find_type & FIND_EVAL)
&& col <= (int)startcol
- && find_is_eval_item((char_u *)ptr + col, &col, &bn, FORWARD)))) {
+ && find_is_eval_item(ptr + col, &col, &bn, FORWARD)))) {
col += utfc_ptr2len(ptr + col);
}
@@ -1906,7 +1926,7 @@ bool add_to_showcmd(int c)
}
}
- char *p = (char *)transchar(c);
+ char *p = transchar(c);
if (*p == ' ') {
STRCPY(p, "<20>");
}
@@ -2191,17 +2211,19 @@ static void nv_addsub(cmdarg_T *cap)
/// CTRL-F, CTRL-B, etc: Scroll page up or down.
static void nv_page(cmdarg_T *cap)
{
- if (!checkclearop(cap->oap)) {
- if (mod_mask & MOD_MASK_CTRL) {
- // <C-PageUp>: tab page back; <C-PageDown>: tab page forward
- if (cap->arg == BACKWARD) {
- goto_tabpage(-(int)cap->count1);
- } else {
- goto_tabpage((int)cap->count0);
- }
+ if (checkclearop(cap->oap)) {
+ return;
+ }
+
+ if (mod_mask & MOD_MASK_CTRL) {
+ // <C-PageUp>: tab page back; <C-PageDown>: tab page forward
+ if (cap->arg == BACKWARD) {
+ goto_tabpage(-(int)cap->count1);
} else {
- (void)onepage(cap->arg, cap->count1);
+ goto_tabpage((int)cap->count0);
}
+ } else {
+ (void)onepage(cap->arg, cap->count1);
}
}
@@ -2213,22 +2235,23 @@ static void nv_gd(oparg_T *oap, int nchar, int thisblock)
size_t len;
char *ptr;
if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0
- || !find_decl((char_u *)ptr, len, nchar == 'd', thisblock, SEARCH_START)) {
+ || !find_decl(ptr, len, nchar == 'd', thisblock, SEARCH_START)) {
clearopbeep(oap);
- } else {
- if ((fdo_flags & FDO_SEARCH) && KeyTyped && oap->op_type == OP_NOP) {
- foldOpenCursor();
- }
- // clear any search statistics
- if (messaging() && !msg_silent && !shortmess(SHM_SEARCHCOUNT)) {
- clear_cmdline = true;
- }
+ return;
+ }
+
+ if ((fdo_flags & FDO_SEARCH) && KeyTyped && oap->op_type == OP_NOP) {
+ foldOpenCursor();
+ }
+ // clear any search statistics
+ if (messaging() && !msg_silent && !shortmess(SHM_SEARCHCOUNT)) {
+ clear_cmdline = true;
}
}
/// @return true if line[offset] is not inside a C-style comment or string,
/// false otherwise.
-static bool is_ident(const char_u *line, int offset)
+static bool is_ident(const char *line, int offset)
{
bool incomment = false;
int instring = 0;
@@ -2236,11 +2259,11 @@ static bool is_ident(const char_u *line, int offset)
for (int i = 0; i < offset && line[i] != NUL; i++) {
if (instring != 0) {
- if (prev != '\\' && line[i] == instring) {
+ if (prev != '\\' && (uint8_t)line[i] == instring) {
instring = 0;
}
} else if ((line[i] == '"' || line[i] == '\'') && !incomment) {
- instring = line[i];
+ instring = (uint8_t)line[i];
} else {
if (incomment) {
if (prev == '*' && line[i] == '/') {
@@ -2253,7 +2276,7 @@ static bool is_ident(const char_u *line, int offset)
}
}
- prev = line[i];
+ prev = (uint8_t)line[i];
}
return incomment == false && instring == 0;
@@ -2267,7 +2290,7 @@ static bool is_ident(const char_u *line, int offset)
/// @param flags_arg flags passed to searchit()
///
/// @return fail when not found.
-bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_arg)
+bool find_decl(char *ptr, size_t len, bool locally, bool thisblock, int flags_arg)
{
char *pat;
pos_T old_pos;
@@ -2285,7 +2308,7 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_
// Put "\V" before the pattern to avoid that the special meaning of "."
// and "~" causes trouble.
assert(len <= INT_MAX);
- sprintf(pat, vim_iswordp((char *)ptr) ? "\\V\\<%.*s\\>" : "\\V%.*s", // NOLINT(runtime/printf)
+ sprintf(pat, vim_iswordp(ptr) ? "\\V\\<%.*s\\>" : "\\V%.*s", // NOLINT(runtime/printf)
(int)len, ptr);
old_pos = curwin->w_cursor;
save_p_ws = p_ws;
@@ -2313,7 +2336,7 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_
clearpos(&found_pos);
for (;;) {
t = searchit(curwin, curbuf, &curwin->w_cursor, NULL, FORWARD,
- (char_u *)pat, 1L, searchflags, RE_LAST, NULL);
+ pat, 1L, searchflags, RE_LAST, NULL);
if (curwin->w_cursor.lnum >= old_pos.lnum) {
t = false; // match after start is failure too
}
@@ -2346,7 +2369,7 @@ bool find_decl(char_u *ptr, size_t len, bool locally, bool thisblock, int flags_
curwin->w_cursor.col = 0;
continue;
}
- bool valid = is_ident((char_u *)get_cursor_line_ptr(), curwin->w_cursor.col);
+ bool valid = is_ident(get_cursor_line_ptr(), curwin->w_cursor.col);
// If the current position is not a valid identifier and a previous match is
// present, favor that one instead.
@@ -2527,7 +2550,7 @@ static bool nv_screengo(oparg_T *oap, int dir, long dist)
validate_virtcol();
colnr_T virtcol = curwin->w_virtcol;
if (virtcol > (colnr_T)width1 && *get_showbreak_value(curwin) != NUL) {
- virtcol -= vim_strsize((char *)get_showbreak_value(curwin));
+ virtcol -= vim_strsize(get_showbreak_value(curwin));
}
int c = utf_ptr2char(get_cursor_pos_ptr());
@@ -3195,44 +3218,45 @@ static void nv_colon(cmdarg_T *cap)
if (VIsual_active && !is_cmdkey && !is_lua) {
nv_operator(cap);
- } else {
- if (cap->oap->op_type != OP_NOP) {
- // Using ":" as a movement is charwise exclusive.
- cap->oap->motion_type = kMTCharWise;
- cap->oap->inclusive = false;
- } else if (cap->count0 && !is_cmdkey && !is_lua) {
- // translate "count:" into ":.,.+(count - 1)"
- stuffcharReadbuff('.');
- if (cap->count0 > 1) {
- stuffReadbuff(",.+");
- stuffnumReadbuff(cap->count0 - 1L);
- }
- }
+ return;
+ }
- // When typing, don't type below an old message
- if (KeyTyped) {
- compute_cmdrow();
+ if (cap->oap->op_type != OP_NOP) {
+ // Using ":" as a movement is charwise exclusive.
+ cap->oap->motion_type = kMTCharWise;
+ cap->oap->inclusive = false;
+ } else if (cap->count0 && !is_cmdkey && !is_lua) {
+ // translate "count:" into ":.,.+(count - 1)"
+ stuffcharReadbuff('.');
+ if (cap->count0 > 1) {
+ stuffReadbuff(",.+");
+ stuffnumReadbuff(cap->count0 - 1L);
}
+ }
- if (is_lua) {
- cmd_result = map_execute_lua();
- } else {
- // get a command line and execute it
- cmd_result = do_cmdline(NULL, is_cmdkey ? getcmdkeycmd : getexline, NULL,
- cap->oap->op_type != OP_NOP ? DOCMD_KEEPLINE : 0);
- }
+ // When typing, don't type below an old message
+ if (KeyTyped) {
+ compute_cmdrow();
+ }
- if (cmd_result == false) {
- // The Ex command failed, do not execute the operator.
- clearop(cap->oap);
- } else if (cap->oap->op_type != OP_NOP
- && (cap->oap->start.lnum > curbuf->b_ml.ml_line_count
- || cap->oap->start.col >
- (colnr_T)strlen(ml_get(cap->oap->start.lnum))
- || did_emsg)) {
- // The start of the operator has become invalid by the Ex command.
- clearopbeep(cap->oap);
- }
+ if (is_lua) {
+ cmd_result = map_execute_lua();
+ } else {
+ // get a command line and execute it
+ cmd_result = do_cmdline(NULL, is_cmdkey ? getcmdkeycmd : getexline, NULL,
+ cap->oap->op_type != OP_NOP ? DOCMD_KEEPLINE : 0);
+ }
+
+ if (cmd_result == false) {
+ // The Ex command failed, do not execute the operator.
+ clearop(cap->oap);
+ } else if (cap->oap->op_type != OP_NOP
+ && (cap->oap->start.lnum > curbuf->b_ml.ml_line_count
+ || cap->oap->start.col >
+ (colnr_T)strlen(ml_get(cap->oap->start.lnum))
+ || did_emsg)) {
+ // The start of the operator has become invalid by the Ex command.
+ clearopbeep(cap->oap);
}
}
@@ -3263,14 +3287,16 @@ static void nv_ctrlh(cmdarg_T *cap)
/// CTRL-L: clear screen and redraw.
static void nv_clear(cmdarg_T *cap)
{
- if (!checkclearop(cap->oap)) {
- // Clear all syntax states to force resyncing.
- syn_stack_free_all(curwin->w_s);
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- wp->w_s->b_syn_slow = false;
- }
- redraw_later(curwin, UPD_CLEAR);
+ if (checkclearop(cap->oap)) {
+ return;
+ }
+
+ // Clear all syntax states to force resyncing.
+ syn_stack_free_all(curwin->w_s);
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ wp->w_s->b_syn_slow = false;
}
+ redraw_later(curwin, UPD_CLEAR);
}
/// CTRL-O: In Select mode: switch to Visual mode for one command.
@@ -3301,21 +3327,23 @@ static void nv_hat(cmdarg_T *cap)
/// "Z" commands.
static void nv_Zet(cmdarg_T *cap)
{
- if (!checkclearopq(cap->oap)) {
- switch (cap->nchar) {
- // "ZZ": equivalent to ":x".
- case 'Z':
- do_cmdline_cmd("x");
- break;
+ if (checkclearopq(cap->oap)) {
+ return;
+ }
- // "ZQ": equivalent to ":q!" (Elvis compatible).
- case 'Q':
- do_cmdline_cmd("q!");
- break;
+ switch (cap->nchar) {
+ // "ZZ": equivalent to ":x".
+ case 'Z':
+ do_cmdline_cmd("x");
+ break;
- default:
- clearopbeep(cap->oap);
- }
+ // "ZQ": equivalent to ":q!" (Elvis compatible).
+ case 'Q':
+ do_cmdline_cmd("q!");
+ break;
+
+ default:
+ clearopbeep(cap->oap);
}
}
@@ -3446,7 +3474,7 @@ static void nv_ident(cmdarg_T *cap)
// Allocate buffer to put the command in. Inserting backslashes can
// double the length of the word. p_kp / curbuf->b_p_kp could be added
// and some numbers.
- char *kp = *curbuf->b_p_kp == NUL ? (char *)p_kp : curbuf->b_p_kp; // 'keywordprg'
+ char *kp = *curbuf->b_p_kp == NUL ? p_kp : curbuf->b_p_kp; // 'keywordprg'
bool kp_help = (*kp == NUL || strcmp(kp, ":he") == 0 || strcmp(kp, ":help") == 0);
if (kp_help && *skipwhite(ptr) == NUL) {
emsg(_(e_noident)); // found white space only
@@ -3532,7 +3560,7 @@ static void nv_ident(cmdarg_T *cap)
p = buf + strlen(buf);
while (n-- > 0) {
// put a backslash before \ and some others
- if (vim_strchr(aux_ptr, *ptr) != NULL) {
+ if (vim_strchr(aux_ptr, (uint8_t)(*ptr)) != NULL) {
*p++ = '\\';
}
// When current byte is a part of multibyte character, copy all
@@ -3846,13 +3874,14 @@ static void nv_up(cmdarg_T *cap)
// <S-Up> is page up
cap->arg = BACKWARD;
nv_page(cap);
- } else {
- cap->oap->motion_type = kMTLineWise;
- if (cursor_up(cap->count1, cap->oap->op_type == OP_NOP) == false) {
- clearopbeep(cap->oap);
- } else if (cap->arg) {
- beginline(BL_WHITE | BL_FIX);
- }
+ return;
+ }
+
+ cap->oap->motion_type = kMTLineWise;
+ if (cursor_up(cap->count1, cap->oap->op_type == OP_NOP) == false) {
+ clearopbeep(cap->oap);
+ } else if (cap->arg) {
+ beginline(BL_WHITE | BL_FIX);
}
}
@@ -3895,15 +3924,11 @@ static void nv_gotofile(cmdarg_T *cap)
char *ptr;
linenr_T lnum = -1;
- if (check_text_locked(cap->oap)) {
- return;
- }
- if (curbuf_locked()) {
- clearop(cap->oap);
+ if (check_text_or_curbuf_locked(cap->oap)) {
return;
}
- ptr = (char *)grab_file_name(cap->count1, &lnum);
+ ptr = grab_file_name(cap->count1, &lnum);
if (ptr != NULL) {
// do autowrite if necessary
@@ -3972,7 +3997,7 @@ static void nv_search(cmdarg_T *cap)
// When using 'incsearch' the cursor may be moved to set a different search
// start position.
- cap->searchbuf = (char *)getcmdline(cap->cmdchar, cap->count1, 0, true);
+ cap->searchbuf = getcmdline(cap->cmdchar, cap->count1, 0, true);
if (cap->searchbuf == NULL) {
clearop(oap);
@@ -4058,22 +4083,23 @@ static void nv_csearch(cmdarg_T *cap)
cap->oap->motion_type = kMTCharWise;
if (IS_SPECIAL(cap->nchar) || searchc(cap, t_cmd) == false) {
clearopbeep(cap->oap);
- } else {
- curwin->w_set_curswant = true;
- // Include a Tab for "tx" and for "dfx".
- if (gchar_cursor() == TAB && virtual_active() && cap->arg == FORWARD
- && (t_cmd || cap->oap->op_type != OP_NOP)) {
- colnr_T scol, ecol;
+ return;
+ }
- getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol);
- curwin->w_cursor.coladd = ecol - scol;
- } else {
- curwin->w_cursor.coladd = 0;
- }
- adjust_for_sel(cap);
- if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP) {
- foldOpenCursor();
- }
+ curwin->w_set_curswant = true;
+ // Include a Tab for "tx" and for "dfx".
+ if (gchar_cursor() == TAB && virtual_active() && cap->arg == FORWARD
+ && (t_cmd || cap->oap->op_type != OP_NOP)) {
+ colnr_T scol, ecol;
+
+ getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol);
+ curwin->w_cursor.coladd = ecol - scol;
+ } else {
+ curwin->w_cursor.coladd = 0;
+ }
+ adjust_for_sel(cap);
+ if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP) {
+ foldOpenCursor();
}
}
@@ -4395,25 +4421,28 @@ static void nv_brace(cmdarg_T *cap)
cap->oap->inclusive = false;
curwin->w_set_curswant = true;
- if (findsent(cap->arg, cap->count1) == false) {
+ if (findsent(cap->arg, cap->count1) == FAIL) {
clearopbeep(cap->oap);
- } else {
- // Don't leave the cursor on the NUL past end of line.
- adjust_cursor(cap->oap);
- curwin->w_cursor.coladd = 0;
- if ((fdo_flags & FDO_BLOCK) && KeyTyped && cap->oap->op_type == OP_NOP) {
- foldOpenCursor();
- }
+ return;
+ }
+
+ // Don't leave the cursor on the NUL past end of line.
+ adjust_cursor(cap->oap);
+ curwin->w_cursor.coladd = 0;
+ if ((fdo_flags & FDO_BLOCK) && KeyTyped && cap->oap->op_type == OP_NOP) {
+ foldOpenCursor();
}
}
/// "m" command: Mark a position.
static void nv_mark(cmdarg_T *cap)
{
- if (!checkclearop(cap->oap)) {
- if (setmark(cap->nchar) == false) {
- clearopbeep(cap->oap);
- }
+ if (checkclearop(cap->oap)) {
+ return;
+ }
+
+ if (setmark(cap->nchar) == false) {
+ clearopbeep(cap->oap);
}
}
@@ -4427,11 +4456,12 @@ static void nv_findpar(cmdarg_T *cap)
curwin->w_set_curswant = true;
if (!findpar(&cap->oap->inclusive, cap->arg, cap->count1, NUL, false)) {
clearopbeep(cap->oap);
- } else {
- curwin->w_cursor.coladd = 0;
- if ((fdo_flags & FDO_BLOCK) && KeyTyped && cap->oap->op_type == OP_NOP) {
- foldOpenCursor();
- }
+ return;
+ }
+
+ curwin->w_cursor.coladd = 0;
+ if ((fdo_flags & FDO_BLOCK) && KeyTyped && cap->oap->op_type == OP_NOP) {
+ foldOpenCursor();
}
}
@@ -4452,14 +4482,16 @@ static void nv_undo(cmdarg_T *cap)
/// <Undo> command.
static void nv_kundo(cmdarg_T *cap)
{
- if (!checkclearopq(cap->oap)) {
- if (bt_prompt(curbuf)) {
- clearopbeep(cap->oap);
- return;
- }
- u_undo((int)cap->count1);
- curwin->w_set_curswant = true;
+ if (checkclearopq(cap->oap)) {
+ return;
}
+
+ if (bt_prompt(curbuf)) {
+ clearopbeep(cap->oap);
+ return;
+ }
+ u_undo((int)cap->count1);
+ curwin->w_set_curswant = true;
}
/// Handle the "r" command.
@@ -4670,15 +4702,20 @@ static void nv_Replace(cmdarg_T *cap)
VIsual_mode_orig = VIsual_mode; // remember original area for gv
VIsual_mode = 'V';
nv_operator(cap);
- } else if (!checkclearopq(cap->oap)) {
- if (!MODIFIABLE(curbuf)) {
- emsg(_(e_modifiable));
- } else {
- if (virtual_active()) {
- coladvance(getviscol());
- }
- invoke_edit(cap, false, cap->arg ? 'V' : 'R', false);
+ return;
+ }
+
+ if (checkclearopq(cap->oap)) {
+ return;
+ }
+
+ if (!MODIFIABLE(curbuf)) {
+ emsg(_(e_modifiable));
+ } else {
+ if (virtual_active()) {
+ coladvance(getviscol());
}
+ invoke_edit(cap, false, cap->arg ? 'V' : 'R', false);
}
}
@@ -4689,20 +4726,25 @@ static void nv_vreplace(cmdarg_T *cap)
cap->cmdchar = 'r';
cap->nchar = cap->extra_char;
nv_replace(cap); // Do same as "r" in Visual mode for now
- } else if (!checkclearopq(cap->oap)) {
- if (!MODIFIABLE(curbuf)) {
- emsg(_(e_modifiable));
- } else {
- if (cap->extra_char == Ctrl_V) { // get another character
- cap->extra_char = get_literal(false);
- }
- stuffcharReadbuff(cap->extra_char);
- stuffcharReadbuff(ESC);
- if (virtual_active()) {
- coladvance(getviscol());
- }
- invoke_edit(cap, true, 'v', false);
+ return;
+ }
+
+ if (checkclearopq(cap->oap)) {
+ return;
+ }
+
+ if (!MODIFIABLE(curbuf)) {
+ emsg(_(e_modifiable));
+ } else {
+ if (cap->extra_char == Ctrl_V) { // get another character
+ cap->extra_char = get_literal(false);
+ }
+ stuffcharReadbuff(cap->extra_char);
+ stuffcharReadbuff(ESC);
+ if (virtual_active()) {
+ coladvance(getviscol());
}
+ invoke_edit(cap, true, 'v', false);
}
}
@@ -4903,42 +4945,44 @@ static void nv_pcmark(cmdarg_T *cap)
MarkMoveRes move_res = 0; // Result from moving to the mark
const bool old_KeyTyped = KeyTyped; // getting file may reset it.
- if (!checkclearopq(cap->oap)) {
- if (cap->cmdchar == TAB && mod_mask == MOD_MASK_CTRL) {
- if (!goto_tabpage_lastused()) {
- clearopbeep(cap->oap);
- }
- return;
- }
+ if (checkclearopq(cap->oap)) {
+ return;
+ }
- if (cap->cmdchar == 'g') {
- fm = get_changelist(curbuf, curwin, (int)cap->count1);
- } else {
- fm = get_jumplist(curwin, (int)cap->count1);
- flags |= KMarkNoContext | kMarkJumpList;
- }
- // Changelist and jumplist have their own error messages. Therefore avoid
- // calling nv_mark_move_to() when not found to avoid incorrect error
- // messages.
- if (fm != NULL) {
- move_res = nv_mark_move_to(cap, flags, fm);
- } else if (cap->cmdchar == 'g') {
- if (curbuf->b_changelistlen == 0) {
- emsg(_("E664: changelist is empty"));
- } else if (cap->count1 < 0) {
- emsg(_("E662: At start of changelist"));
- } else {
- emsg(_("E663: At end of changelist"));
- }
- } else {
+ if (cap->cmdchar == TAB && mod_mask == MOD_MASK_CTRL) {
+ if (!goto_tabpage_lastused()) {
clearopbeep(cap->oap);
}
- if (cap->oap->op_type == OP_NOP
- && (move_res & kMarkSwitchedBuf || move_res & kMarkChangedLine)
- && (fdo_flags & FDO_MARK)
- && old_KeyTyped) {
- foldOpenCursor();
+ return;
+ }
+
+ if (cap->cmdchar == 'g') {
+ fm = get_changelist(curbuf, curwin, (int)cap->count1);
+ } else {
+ fm = get_jumplist(curwin, (int)cap->count1);
+ flags |= KMarkNoContext | kMarkJumpList;
+ }
+ // Changelist and jumplist have their own error messages. Therefore avoid
+ // calling nv_mark_move_to() when not found to avoid incorrect error
+ // messages.
+ if (fm != NULL) {
+ move_res = nv_mark_move_to(cap, flags, fm);
+ } else if (cap->cmdchar == 'g') {
+ if (curbuf->b_changelistlen == 0) {
+ emsg(_("E664: changelist is empty"));
+ } else if (cap->count1 < 0) {
+ emsg(_("E662: At start of changelist"));
+ } else {
+ emsg(_("E663: At end of changelist"));
}
+ } else {
+ clearopbeep(cap->oap);
+ }
+ if (cap->oap->op_type == OP_NOP
+ && (move_res & kMarkSwitchedBuf || move_res & kMarkChangedLine)
+ && (fdo_flags & FDO_MARK)
+ && old_KeyTyped) {
+ foldOpenCursor();
}
}
@@ -5028,9 +5072,13 @@ static void nv_visual(cmdarg_T *cap)
curwin->w_curswant = MAXCOL;
coladvance(MAXCOL);
} else if (VIsual_mode == Ctrl_V) {
+ // Update curswant on the original line, that is where "col" is valid.
+ linenr_T lnum = curwin->w_cursor.lnum;
+ curwin->w_cursor.lnum = VIsual.lnum;
update_curswant_force();
assert(cap->count0 >= INT_MIN && cap->count0 <= INT_MAX);
curwin->w_curswant += resel_VIsual_vcol * (int)cap->count0 - 1;
+ curwin->w_cursor.lnum = lnum;
coladvance(curwin->w_curswant);
} else {
curwin->w_set_curswant = true;
@@ -5669,42 +5717,46 @@ static void nv_g_cmd(cmdarg_T *cap)
/// Handle "o" and "O" commands.
static void n_opencmd(cmdarg_T *cap)
{
- if (!checkclearopq(cap->oap)) {
- if (cap->cmdchar == 'O') {
- // Open above the first line of a folded sequence of lines
- (void)hasFolding(curwin->w_cursor.lnum,
- &curwin->w_cursor.lnum, NULL);
- } else {
- // Open below the last line of a folded sequence of lines
- (void)hasFolding(curwin->w_cursor.lnum,
- NULL, &curwin->w_cursor.lnum);
- }
- if (u_save((linenr_T)(curwin->w_cursor.lnum -
- (cap->cmdchar == 'O' ? 1 : 0)),
- (linenr_T)(curwin->w_cursor.lnum +
- (cap->cmdchar == 'o' ? 1 : 0)))
- && open_line(cap->cmdchar == 'O' ? BACKWARD : FORWARD,
- has_format_option(FO_OPEN_COMS) ? OPENLINE_DO_COM : 0,
- 0, NULL)) {
- if (win_cursorline_standout(curwin)) {
- // force redraw of cursorline
- curwin->w_valid &= ~VALID_CROW;
- }
- invoke_edit(cap, false, cap->cmdchar, true);
+ if (checkclearopq(cap->oap)) {
+ return;
+ }
+
+ if (cap->cmdchar == 'O') {
+ // Open above the first line of a folded sequence of lines
+ (void)hasFolding(curwin->w_cursor.lnum,
+ &curwin->w_cursor.lnum, NULL);
+ } else {
+ // Open below the last line of a folded sequence of lines
+ (void)hasFolding(curwin->w_cursor.lnum,
+ NULL, &curwin->w_cursor.lnum);
+ }
+ if (u_save((linenr_T)(curwin->w_cursor.lnum -
+ (cap->cmdchar == 'O' ? 1 : 0)),
+ (linenr_T)(curwin->w_cursor.lnum +
+ (cap->cmdchar == 'o' ? 1 : 0)))
+ && open_line(cap->cmdchar == 'O' ? BACKWARD : FORWARD,
+ has_format_option(FO_OPEN_COMS) ? OPENLINE_DO_COM : 0,
+ 0, NULL)) {
+ if (win_cursorline_standout(curwin)) {
+ // force redraw of cursorline
+ curwin->w_valid &= ~VALID_CROW;
}
+ invoke_edit(cap, false, cap->cmdchar, true);
}
}
/// "." command: redo last change.
static void nv_dot(cmdarg_T *cap)
{
- if (!checkclearopq(cap->oap)) {
- // If "restart_edit" is true, the last but one command is repeated
- // instead of the last command (inserting text). This is used for
- // CTRL-O <.> in insert mode.
- if (start_redo(cap->count0, restart_edit != 0 && !arrow_used) == false) {
- clearopbeep(cap->oap);
- }
+ if (checkclearopq(cap->oap)) {
+ return;
+ }
+
+ // If "restart_edit" is true, the last but one command is repeated
+ // instead of the last command (inserting text). This is used for
+ // CTRL-O <.> in insert mode.
+ if (start_redo(cap->count0, restart_edit != 0 && !arrow_used) == false) {
+ clearopbeep(cap->oap);
}
}
@@ -5728,10 +5780,12 @@ static void nv_redo_or_register(cmdarg_T *cap)
return;
}
- if (!checkclearopq(cap->oap)) {
- u_redo((int)cap->count1);
- curwin->w_set_curswant = true;
+ if (checkclearopq(cap->oap)) {
+ return;
}
+
+ u_redo((int)cap->count1);
+ curwin->w_set_curswant = true;
}
/// Handle "U" command.
@@ -5743,10 +5797,15 @@ static void nv_Undo(cmdarg_T *cap)
cap->cmdchar = 'g';
cap->nchar = 'U';
nv_operator(cap);
- } else if (!checkclearopq(cap->oap)) {
- u_undoline();
- curwin->w_set_curswant = true;
+ return;
}
+
+ if (checkclearopq(cap->oap)) {
+ return;
+ }
+
+ u_undoline();
+ curwin->w_set_curswant = true;
}
/// '~' command: If tilde is not an operator and Visual is off: swap case of a
@@ -6309,16 +6368,21 @@ static void nv_record(cmdarg_T *cap)
cap->cmdchar = 'g';
cap->nchar = 'q';
nv_operator(cap);
- } else if (!checkclearop(cap->oap)) {
- if (cap->nchar == ':' || cap->nchar == '/' || cap->nchar == '?') {
- stuffcharReadbuff(cap->nchar);
- stuffcharReadbuff(K_CMDWIN);
- } else {
- // (stop) recording into a named register, unless executing a
- // register.
- if (reg_executing == 0 && do_record(cap->nchar) == FAIL) {
- clearopbeep(cap->oap);
- }
+ return;
+ }
+
+ if (checkclearop(cap->oap)) {
+ return;
+ }
+
+ if (cap->nchar == ':' || cap->nchar == '/' || cap->nchar == '?') {
+ stuffcharReadbuff(cap->nchar);
+ stuffcharReadbuff(K_CMDWIN);
+ } else {
+ // (stop) recording into a named register, unless executing a
+ // register.
+ if (reg_executing == 0 && do_record(cap->nchar) == FAIL) {
+ clearopbeep(cap->oap);
}
}
}
@@ -6360,24 +6424,29 @@ static void nv_join(cmdarg_T *cap)
{
if (VIsual_active) { // join the visual lines
nv_operator(cap);
- } else if (!checkclearop(cap->oap)) {
- if (cap->count0 <= 1) {
- cap->count0 = 2; // default for join is two lines!
- }
- if (curwin->w_cursor.lnum + cap->count0 - 1 >
- curbuf->b_ml.ml_line_count) {
- // can't join when on the last line
- if (cap->count0 <= 2) {
- clearopbeep(cap->oap);
- return;
- }
- cap->count0 = curbuf->b_ml.ml_line_count - curwin->w_cursor.lnum + 1;
- }
+ return;
+ }
- prep_redo(cap->oap->regname, cap->count0,
- NUL, cap->cmdchar, NUL, NUL, cap->nchar);
- do_join((size_t)cap->count0, cap->nchar == NUL, true, true, true);
+ if (checkclearop(cap->oap)) {
+ return;
}
+
+ if (cap->count0 <= 1) {
+ cap->count0 = 2; // default for join is two lines!
+ }
+ if (curwin->w_cursor.lnum + cap->count0 - 1 >
+ curbuf->b_ml.ml_line_count) {
+ // can't join when on the last line
+ if (cap->count0 <= 2) {
+ clearopbeep(cap->oap);
+ return;
+ }
+ cap->count0 = curbuf->b_ml.ml_line_count - curwin->w_cursor.lnum + 1;
+ }
+
+ prep_redo(cap->oap->regname, cap->count0,
+ NUL, cap->cmdchar, NUL, NUL, cap->nchar);
+ do_join((size_t)cap->count0, cap->nchar == NUL, true, true, true);
}
/// "P", "gP", "p" and "gp" commands.
@@ -6407,117 +6476,121 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent)
} else {
clearopbeep(cap->oap);
}
- } else if (bt_prompt(curbuf) && !prompt_curpos_editable()) {
- clearopbeep(cap->oap);
- } else {
- if (fix_indent) {
- dir = (cap->cmdchar == ']' && cap->nchar == 'p')
- ? FORWARD : BACKWARD;
- flags |= PUT_FIXINDENT;
- } else {
- dir = (cap->cmdchar == 'P'
- || ((cap->cmdchar == 'g' || cap->cmdchar == 'z')
- && cap->nchar == 'P')) ? BACKWARD : FORWARD;
- }
- prep_redo_cmd(cap);
- if (cap->cmdchar == 'g') {
- flags |= PUT_CURSEND;
- } else if (cap->cmdchar == 'z') {
- flags |= PUT_BLOCK_INNER;
- }
+ return;
+ }
- if (VIsual_active) {
- // Putting in Visual mode: The put text replaces the selected
- // text. First delete the selected text, then put the new text.
- // Need to save and restore the registers that the delete
- // overwrites if the old contents is being put.
- was_visual = true;
- regname = cap->oap->regname;
- bool keep_registers = cap->cmdchar == 'P';
- // '+' and '*' could be the same selection
- bool clipoverwrite = (regname == '+' || regname == '*') && (cb_flags & CB_UNNAMEDMASK);
- if (regname == 0 || regname == '"' || clipoverwrite
- || ascii_isdigit(regname) || regname == '-') {
- // The delete might overwrite the register we want to put, save it first
- savereg = copy_register(regname);
- }
+ if (bt_prompt(curbuf) && !prompt_curpos_editable()) {
+ clearopbeep(cap->oap);
+ return;
+ }
- // To place the cursor correctly after a blockwise put, and to leave the
- // text in the correct position when putting over a selection with
- // 'virtualedit' and past the end of the line, we use the 'c' operator in
- // do_put(), which requires the visual selection to still be active.
- if (!VIsual_active || VIsual_mode == 'V' || regname != '.') {
- // Now delete the selected text. Avoid messages here.
- cap->cmdchar = 'd';
- cap->nchar = NUL;
- cap->oap->regname = keep_registers ? '_' : NUL;
- msg_silent++;
- nv_operator(cap);
- do_pending_operator(cap, 0, false);
- empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
- msg_silent--;
+ if (fix_indent) {
+ dir = (cap->cmdchar == ']' && cap->nchar == 'p')
+ ? FORWARD : BACKWARD;
+ flags |= PUT_FIXINDENT;
+ } else {
+ dir = (cap->cmdchar == 'P'
+ || ((cap->cmdchar == 'g' || cap->cmdchar == 'z')
+ && cap->nchar == 'P')) ? BACKWARD : FORWARD;
+ }
+ prep_redo_cmd(cap);
+ if (cap->cmdchar == 'g') {
+ flags |= PUT_CURSEND;
+ } else if (cap->cmdchar == 'z') {
+ flags |= PUT_BLOCK_INNER;
+ }
- // delete PUT_LINE_BACKWARD;
- cap->oap->regname = regname;
- }
+ if (VIsual_active) {
+ // Putting in Visual mode: The put text replaces the selected
+ // text. First delete the selected text, then put the new text.
+ // Need to save and restore the registers that the delete
+ // overwrites if the old contents is being put.
+ was_visual = true;
+ regname = cap->oap->regname;
+ bool keep_registers = cap->cmdchar == 'P';
+ // '+' and '*' could be the same selection
+ bool clipoverwrite = (regname == '+' || regname == '*') && (cb_flags & CB_UNNAMEDMASK);
+ if (regname == 0 || regname == '"' || clipoverwrite
+ || ascii_isdigit(regname) || regname == '-') {
+ // The delete might overwrite the register we want to put, save it first
+ savereg = copy_register(regname);
+ }
+
+ // To place the cursor correctly after a blockwise put, and to leave the
+ // text in the correct position when putting over a selection with
+ // 'virtualedit' and past the end of the line, we use the 'c' operator in
+ // do_put(), which requires the visual selection to still be active.
+ if (!VIsual_active || VIsual_mode == 'V' || regname != '.') {
+ // Now delete the selected text. Avoid messages here.
+ cap->cmdchar = 'd';
+ cap->nchar = NUL;
+ cap->oap->regname = keep_registers ? '_' : NUL;
+ msg_silent++;
+ nv_operator(cap);
+ do_pending_operator(cap, 0, false);
+ empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
+ msg_silent--;
- // When deleted a linewise Visual area, put the register as
- // lines to avoid it joined with the next line. When deletion was
- // charwise, split a line when putting lines.
- if (VIsual_mode == 'V') {
- flags |= PUT_LINE;
- } else if (VIsual_mode == 'v') {
- flags |= PUT_LINE_SPLIT;
- }
- if (VIsual_mode == Ctrl_V && dir == FORWARD) {
- flags |= PUT_LINE_FORWARD;
- }
- dir = BACKWARD;
- if ((VIsual_mode != 'V'
- && curwin->w_cursor.col < curbuf->b_op_start.col)
- || (VIsual_mode == 'V'
- && curwin->w_cursor.lnum < curbuf->b_op_start.lnum)) {
- // cursor is at the end of the line or end of file, put
- // forward.
- dir = FORWARD;
- }
- // May have been reset in do_put().
- VIsual_active = true;
+ // delete PUT_LINE_BACKWARD;
+ cap->oap->regname = regname;
}
- do_put(cap->oap->regname, savereg, dir, cap->count1, flags);
- // If a register was saved, free it
- if (savereg != NULL) {
- free_register(savereg);
- xfree(savereg);
+ // When deleted a linewise Visual area, put the register as
+ // lines to avoid it joined with the next line. When deletion was
+ // charwise, split a line when putting lines.
+ if (VIsual_mode == 'V') {
+ flags |= PUT_LINE;
+ } else if (VIsual_mode == 'v') {
+ flags |= PUT_LINE_SPLIT;
+ }
+ if (VIsual_mode == Ctrl_V && dir == FORWARD) {
+ flags |= PUT_LINE_FORWARD;
+ }
+ dir = BACKWARD;
+ if ((VIsual_mode != 'V'
+ && curwin->w_cursor.col < curbuf->b_op_start.col)
+ || (VIsual_mode == 'V'
+ && curwin->w_cursor.lnum < curbuf->b_op_start.lnum)) {
+ // cursor is at the end of the line or end of file, put
+ // forward.
+ dir = FORWARD;
}
+ // May have been reset in do_put().
+ VIsual_active = true;
+ }
+ do_put(cap->oap->regname, savereg, dir, cap->count1, flags);
- // What to reselect with "gv"? Selecting the just put text seems to
- // be the most useful, since the original text was removed.
- if (was_visual) {
- curbuf->b_visual.vi_start = curbuf->b_op_start;
- curbuf->b_visual.vi_end = curbuf->b_op_end;
- // need to adjust cursor position
- if (*p_sel == 'e') {
- inc(&curbuf->b_visual.vi_end);
- }
+ // If a register was saved, free it
+ if (savereg != NULL) {
+ free_register(savereg);
+ xfree(savereg);
+ }
+
+ // What to reselect with "gv"? Selecting the just put text seems to
+ // be the most useful, since the original text was removed.
+ if (was_visual) {
+ curbuf->b_visual.vi_start = curbuf->b_op_start;
+ curbuf->b_visual.vi_end = curbuf->b_op_end;
+ // need to adjust cursor position
+ if (*p_sel == 'e') {
+ inc(&curbuf->b_visual.vi_end);
}
+ }
- // When all lines were selected and deleted do_put() leaves an empty
- // line that needs to be deleted now.
- if (empty && *ml_get(curbuf->b_ml.ml_line_count) == NUL) {
- ml_delete(curbuf->b_ml.ml_line_count, true);
- deleted_lines(curbuf->b_ml.ml_line_count + 1, 1);
+ // When all lines were selected and deleted do_put() leaves an empty
+ // line that needs to be deleted now.
+ if (empty && *ml_get(curbuf->b_ml.ml_line_count) == NUL) {
+ ml_delete(curbuf->b_ml.ml_line_count, true);
+ deleted_lines(curbuf->b_ml.ml_line_count + 1, 1);
- // If the cursor was in that line, move it to the end of the last
- // line.
- if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) {
- curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
- coladvance(MAXCOL);
- }
+ // If the cursor was in that line, move it to the end of the last
+ // line.
+ if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) {
+ curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
+ coladvance(MAXCOL);
}
- auto_format(false, true);
}
+ auto_format(false, true);
}
/// "o" and "O" commands.
diff --git a/src/nvim/normal.h b/src/nvim/normal.h
index 90a5c4103e..bed1a40b97 100644
--- a/src/nvim/normal.h
+++ b/src/nvim/normal.h
@@ -4,6 +4,7 @@
#include <stdbool.h>
#include "nvim/buffer_defs.h"
+#include "nvim/macros.h"
#include "nvim/pos.h"
// Values for find_ident_under_cursor()
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 34432c58db..435ca106ab 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -723,7 +723,7 @@ int get_expr_register(void)
{
char *new_line;
- new_line = (char *)getcmdline('=', 0L, 0, true);
+ new_line = getcmdline('=', 0L, 0, true);
if (new_line == NULL) {
return NUL;
}
@@ -1006,7 +1006,7 @@ static int stuff_yank(int regname, char *p)
} else {
free_register(reg);
set_yreg_additional_data(reg, NULL);
- reg->y_array = xmalloc(sizeof(char_u *));
+ reg->y_array = xmalloc(sizeof(char *));
reg->y_array[0] = p;
reg->y_size = 1;
reg->y_type = kMTCharWise;
@@ -1028,14 +1028,14 @@ static int execreg_lastc = NUL;
/// with a \. Lines that start with a comment "\ character are ignored.
/// @returns the concatenated line. The index of the line that should be
/// processed next is returned in idx.
-static char_u *execreg_line_continuation(char **lines, size_t *idx)
+static char *execreg_line_continuation(char **lines, size_t *idx)
{
size_t i = *idx;
assert(i > 0);
const size_t cmd_end = i;
garray_T ga;
- ga_init(&ga, (int)sizeof(char_u), 400);
+ ga_init(&ga, (int)sizeof(char), 400);
char *p;
@@ -1068,7 +1068,7 @@ static char_u *execreg_line_continuation(char **lines, size_t *idx)
ga_clear(&ga);
*idx = i;
- return (char_u *)str;
+ return str;
}
/// Execute a yank register: copy it into the stuff buffer
@@ -1118,9 +1118,9 @@ int do_execreg(int regname, int colon, int addcr, int silent)
// When in Visual mode "'<,'>" will be prepended to the command.
// Remove it when it's already there.
if (VIsual_active && strncmp(p, "'<,'>", 5) == 0) {
- retval = put_in_typebuf((char_u *)p + 5, true, true, silent);
+ retval = put_in_typebuf(p + 5, true, true, silent);
} else {
- retval = put_in_typebuf((char_u *)p, true, true, silent);
+ retval = put_in_typebuf(p, true, true, silent);
}
xfree(p);
} else if (regname == '=') {
@@ -1128,15 +1128,15 @@ int do_execreg(int regname, int colon, int addcr, int silent)
if (p == NULL) {
return FAIL;
}
- retval = put_in_typebuf((char_u *)p, true, colon, silent);
+ retval = put_in_typebuf(p, true, colon, silent);
xfree(p);
} else if (regname == '.') { // use last inserted text
- p = (char *)get_last_insert_save();
+ p = get_last_insert_save();
if (p == NULL) {
emsg(_(e_noinstext));
return FAIL;
}
- retval = put_in_typebuf((char_u *)p, false, colon, silent);
+ retval = put_in_typebuf(p, false, colon, silent);
xfree(p);
} else {
yankreg_T *reg = get_yank_register(regname, YREG_PASTE);
@@ -1164,7 +1164,7 @@ int do_execreg(int regname, int colon, int addcr, int silent)
if (colon && i > 0) {
p = skipwhite(str);
if (*p == '\\' || (p[0] == '"' && p[1] == '\\' && p[2] == ' ')) {
- str = (char *)execreg_line_continuation(reg->y_array, &i);
+ str = execreg_line_continuation(reg->y_array, &i);
free_str = true;
}
}
@@ -1193,18 +1193,20 @@ static void put_reedit_in_typebuf(int silent)
{
char_u buf[3];
- if (restart_edit != NUL) {
- if (restart_edit == 'V') {
- buf[0] = 'g';
- buf[1] = 'R';
- buf[2] = NUL;
- } else {
- buf[0] = (char_u)(restart_edit == 'I' ? 'i' : restart_edit);
- buf[1] = NUL;
- }
- if (ins_typebuf((char *)buf, REMAP_NONE, 0, true, silent) == OK) {
- restart_edit = NUL;
- }
+ if (restart_edit == NUL) {
+ return;
+ }
+
+ if (restart_edit == 'V') {
+ buf[0] = 'g';
+ buf[1] = 'R';
+ buf[2] = NUL;
+ } else {
+ buf[0] = (char_u)(restart_edit == 'I' ? 'i' : restart_edit);
+ buf[1] = NUL;
+ }
+ if (ins_typebuf((char *)buf, REMAP_NONE, 0, true, silent) == OK) {
+ restart_edit = NUL;
}
}
@@ -1214,7 +1216,7 @@ static void put_reedit_in_typebuf(int silent)
/// @param esc when true then it is to be taken literally: Escape K_SPECIAL
/// characters and no remapping.
/// @param colon add ':' before the line
-static int put_in_typebuf(char_u *s, bool esc, bool colon, int silent)
+static int put_in_typebuf(char *s, bool esc, bool colon, int silent)
{
int retval = OK;
@@ -1226,9 +1228,9 @@ static int put_in_typebuf(char_u *s, bool esc, bool colon, int silent)
char *p;
if (esc) {
- p = vim_strsave_escape_ks((char *)s);
+ p = vim_strsave_escape_ks(s);
} else {
- p = (char *)s;
+ p = s;
}
if (p == NULL) {
retval = FAIL;
@@ -1347,11 +1349,11 @@ bool get_spec_reg(int regname, char **argp, bool *allocated, bool errmsg)
if (last_search_pat() == NULL && errmsg) {
emsg(_(e_noprevre));
}
- *argp = (char *)last_search_pat();
+ *argp = last_search_pat();
return true;
case '.': // last inserted text
- *argp = (char *)get_last_insert_save();
+ *argp = get_last_insert_save();
*allocated = true;
if (*argp == NULL && errmsg) {
emsg(_(e_noinstext));
@@ -1363,9 +1365,8 @@ bool get_spec_reg(int regname, char **argp, bool *allocated, bool errmsg)
if (!errmsg) {
return false;
}
- *argp
- = (char *)file_name_at_cursor(FNAME_MESS | FNAME_HYP | (regname == Ctrl_P ? FNAME_EXP : 0),
- 1L, NULL);
+ *argp = file_name_at_cursor(FNAME_MESS | FNAME_HYP | (regname == Ctrl_P ? FNAME_EXP : 0),
+ 1L, NULL);
*allocated = true;
return true;
@@ -1418,11 +1419,11 @@ bool cmdline_paste_reg(int regname, bool literally_arg, bool remcr)
}
for (size_t i = 0; i < reg->y_size; i++) {
- cmdline_paste_str((char_u *)reg->y_array[i], literally);
+ cmdline_paste_str(reg->y_array[i], literally);
// Insert ^M between lines, unless `remcr` is true.
if (i < reg->y_size - 1 && !remcr) {
- cmdline_paste_str((char_u *)"\r", literally);
+ cmdline_paste_str("\r", literally);
}
// Check for CTRL-C, in case someone tries to paste a few thousand
@@ -1455,7 +1456,7 @@ int op_delete(oparg_T *oap)
{
int n;
linenr_T lnum;
- char_u *ptr;
+ char *ptr;
char *newp, *oldp;
struct block_def bd = { 0 };
linenr_T old_lcount = curbuf->b_ml.ml_line_count;
@@ -1489,11 +1490,11 @@ int op_delete(oparg_T *oap)
&& oap->line_count > 1
&& oap->motion_force == NUL
&& oap->op_type == OP_DELETE) {
- ptr = (char_u *)ml_get(oap->end.lnum) + oap->end.col;
+ ptr = ml_get(oap->end.lnum) + oap->end.col;
if (*ptr != NUL) {
ptr += oap->inclusive;
}
- ptr = (char_u *)skipwhite((char *)ptr);
+ ptr = skipwhite(ptr);
if (*ptr == NUL && inindent(0)) {
oap->motion_type = kMTLineWise;
}
@@ -1785,10 +1786,12 @@ setmarks:
/// Used for deletion.
static void mb_adjust_opend(oparg_T *oap)
{
- if (oap->inclusive) {
- char *p = ml_get(oap->end.lnum);
- oap->end.col += utf_cp_tail_off(p, p + oap->end.col);
+ if (!oap->inclusive) {
+ return;
}
+
+ char *p = ml_get(oap->end.lnum);
+ oap->end.col += utf_cp_tail_off(p, p + oap->end.col);
}
/// Put character 'c' at position 'lp'
@@ -2573,12 +2576,14 @@ void free_register(yankreg_T *reg)
FUNC_ATTR_NONNULL_ALL
{
set_yreg_additional_data(reg, NULL);
- if (reg->y_array != NULL) {
- for (size_t i = reg->y_size; i-- > 0;) { // from y_size - 1 to 0 included
- xfree(reg->y_array[i]);
- }
- XFREE_CLEAR(reg->y_array);
+ if (reg->y_array == NULL) {
+ return;
+ }
+
+ for (size_t i = reg->y_size; i-- > 0;) { // from y_size - 1 to 0 included
+ xfree(reg->y_array[i]);
}
+ XFREE_CLEAR(reg->y_array);
}
/// Yanks the text between "oap->start" and "oap->end" into a yank register.
@@ -2738,7 +2743,7 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
}
if (curr != reg) { // append the new block to the old block
- new_ptr = xmalloc(sizeof(char_u *) * (curr->y_size + reg->y_size));
+ new_ptr = xmalloc(sizeof(char *) * (curr->y_size + reg->y_size));
for (j = 0; j < curr->y_size; j++) {
new_ptr[j] = curr->y_array[j];
}
@@ -3081,7 +3086,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
if (y_array != NULL) {
break;
}
- y_array = xmalloc(y_size * sizeof(char_u *));
+ y_array = xmalloc(y_size * sizeof(char *));
}
} else {
y_size = 1; // use fake one-line yank register
@@ -3146,7 +3151,7 @@ void do_put(int regname, yankreg_T *reg, int dir, long count, int flags)
if (y_size == 0 || y_array == NULL) {
semsg(_("E353: Nothing in register %s"),
- regname == 0 ? (char_u *)"\"" : transchar(regname));
+ regname == 0 ? "\"" : transchar(regname));
goto end;
}
@@ -3711,20 +3716,23 @@ void adjust_cursor_eol(void)
{
unsigned int cur_ve_flags = get_ve_flags();
- if (curwin->w_cursor.col > 0
- && gchar_cursor() == NUL
- && (cur_ve_flags & VE_ONEMORE) == 0
- && !(restart_edit || (State & MODE_INSERT))) {
- // Put the cursor on the last character in the line.
- dec_cursor();
+ const bool adj_cursor = (curwin->w_cursor.col > 0
+ && gchar_cursor() == NUL
+ && (cur_ve_flags & VE_ONEMORE) == 0
+ && !(restart_edit || (State & MODE_INSERT)));
+ if (!adj_cursor) {
+ return;
+ }
- if (cur_ve_flags == VE_ALL) {
- colnr_T scol, ecol;
+ // Put the cursor on the last character in the line.
+ dec_cursor();
- // Coladd is set to the width of the last character.
- getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol);
- curwin->w_cursor.coladd = ecol - scol + 1;
- }
+ if (cur_ve_flags == VE_ALL) {
+ colnr_T scol, ecol;
+
+ // Coladd is set to the width of the last character.
+ getvcol(curwin, &curwin->w_cursor, &scol, NULL, &ecol);
+ curwin->w_cursor.coladd = ecol - scol + 1;
}
}
@@ -3884,9 +3892,9 @@ void ex_display(exarg_T *eap)
// display last search pattern
if (last_search_pat() != NULL
&& (arg == NULL || vim_strchr(arg, '/') != NULL) && !got_int
- && !message_filtered((char *)last_search_pat())) {
+ && !message_filtered(last_search_pat())) {
msg_puts("\n c \"/ ");
- dis_msg((char *)last_search_pat(), false);
+ dis_msg(last_search_pat(), false);
}
// display last used expression
@@ -4205,11 +4213,13 @@ static bool reset_lbr(void)
/// Restore 'linebreak' and take care of side effects.
static void restore_lbr(bool lbr_saved)
{
- if (!curwin->w_p_lbr && lbr_saved) {
- // changing 'linebreak' may require w_virtcol to be updated
- curwin->w_p_lbr = true;
- curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL);
+ if (curwin->w_p_lbr || !lbr_saved) {
+ return;
}
+
+ // changing 'linebreak' may require w_virtcol to be updated
+ curwin->w_p_lbr = true;
+ curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL);
}
/// prepare a few things for block mode yank/delete/tilde
@@ -4468,7 +4478,7 @@ void op_addsub(oparg_T *oap, linenr_T Prenum1, bool g_cmd)
int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
{
int col;
- char_u *buf1 = NULL;
+ char *buf1 = NULL;
char buf2[NUMBUFLEN];
int pre; // 'X' or 'x': hex; '0': octal; 'B' or 'b': bin
static bool hexupper = false; // 0xABC
@@ -4740,7 +4750,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
// When there are many leading zeros it could be very long.
// Allocate a bit too much.
buf1 = xmalloc((size_t)length + NUMBUFLEN);
- ptr = (char *)buf1;
+ ptr = buf1;
if (negative && (!visual || was_positive)) {
*ptr++ = '-';
}
@@ -4792,7 +4802,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
}
*ptr = NUL;
STRCAT(buf1, buf2);
- ins_str((char *)buf1); // insert the new number
+ ins_str(buf1); // insert the new number
endpos = curwin->w_cursor;
if (curwin->w_cursor.col) {
curwin->w_cursor.col--;
@@ -5081,7 +5091,7 @@ void write_reg_contents_ex(int name, const char *str, ssize_t len, bool must_app
// Special case: '/' search pattern
if (name == '/') {
- set_last_search_pat((char_u *)str, RE_SEARCH, true, true);
+ set_last_search_pat(str, RE_SEARCH, true, true);
return;
}
@@ -5171,7 +5181,7 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str,
// Count the number of lines within the string
if (str_list) {
- for (char_u **ss = (char_u **)str; *ss != NULL; ss++) {
+ for (char **ss = (char **)str; *ss != NULL; ss++) {
newlines++;
}
} else {
@@ -5193,7 +5203,7 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str,
}
// Grow the register array to hold the pointers to the new lines.
- char **pp = xrealloc(y_ptr->y_array, (y_ptr->y_size + newlines) * sizeof(char_u *));
+ char **pp = xrealloc(y_ptr->y_array, (y_ptr->y_size + newlines) * sizeof(char *));
y_ptr->y_array = pp;
size_t lnum = y_ptr->y_size; // The current line number.
@@ -5212,12 +5222,11 @@ static void str_to_reg(yankreg_T *y_ptr, MotionType yank_type, const char *str,
}
} else {
size_t line_len;
- for (const char_u *start = (char_u *)str, *end = (char_u *)str + len;
+ for (const char *start = str, *end = str + len;
start < end + extraline;
start += line_len + 1, lnum++) {
assert(end - start >= 0);
- line_len = (size_t)((char_u *)xmemscan(start, '\n',
- (size_t)(end - start)) - start);
+ line_len = (size_t)((char *)xmemscan(start, '\n', (size_t)(end - start)) - start);
if (line_len > maxlen) {
maxlen = line_len;
}
@@ -5269,8 +5278,8 @@ void clear_oparg(oparg_T *oap)
/// line, stopping if it encounters an end-of-line (NUL byte). In that
/// case, eol_size will be added to the character count to account for
/// the size of the EOL character.
-static varnumber_T line_count_info(char_u *line, varnumber_T *wc, varnumber_T *cc,
- varnumber_T limit, int eol_size)
+static varnumber_T line_count_info(char *line, varnumber_T *wc, varnumber_T *cc, varnumber_T limit,
+ int eol_size)
{
varnumber_T i;
varnumber_T words = 0;
@@ -5287,7 +5296,7 @@ static varnumber_T line_count_info(char_u *line, varnumber_T *wc, varnumber_T *c
is_word = 1;
}
chars++;
- i += utfc_ptr2len((char *)line + i);
+ i += utfc_ptr2len(line + i);
}
if (is_word) {
@@ -5312,8 +5321,8 @@ static varnumber_T line_count_info(char_u *line, varnumber_T *wc, varnumber_T *c
void cursor_pos_info(dict_T *dict)
{
char *p;
- char_u buf1[50];
- char_u buf2[40];
+ char buf1[50];
+ char buf2[40];
linenr_T lnum;
varnumber_T byte_count = 0;
varnumber_T bom_count = 0;
@@ -5422,7 +5431,7 @@ void cursor_pos_info(dict_T *dict)
break;
}
if (s != NULL) {
- byte_count_cursor += line_count_info((char_u *)s, &word_count_cursor,
+ byte_count_cursor += line_count_info(s, &word_count_cursor,
&char_count_cursor, len, eol_size);
if (lnum == curbuf->b_ml.ml_line_count
&& !curbuf->b_p_eol
@@ -5437,14 +5446,14 @@ void cursor_pos_info(dict_T *dict)
word_count_cursor += word_count;
char_count_cursor += char_count;
byte_count_cursor = byte_count
- + line_count_info((char_u *)ml_get(lnum), &word_count_cursor,
+ + line_count_info(ml_get(lnum), &word_count_cursor,
&char_count_cursor,
(varnumber_T)curwin->w_cursor.col + 1,
eol_size);
}
}
// Add to the running totals
- byte_count += line_count_info((char_u *)ml_get(lnum), &word_count, &char_count,
+ byte_count += line_count_info(ml_get(lnum), &word_count, &char_count,
(varnumber_T)MAXCOL, eol_size);
}
@@ -5459,7 +5468,7 @@ void cursor_pos_info(dict_T *dict)
getvcols(curwin, &min_pos, &max_pos, &min_pos.col, &max_pos.col);
int64_t cols;
STRICT_SUB(oparg.end_vcol + 1, oparg.start_vcol, &cols, int64_t);
- vim_snprintf((char *)buf1, sizeof(buf1), _("%" PRId64 " Cols; "),
+ vim_snprintf(buf1, sizeof(buf1), _("%" PRId64 " Cols; "),
cols);
} else {
buf1[0] = NUL;
@@ -5490,7 +5499,7 @@ void cursor_pos_info(dict_T *dict)
} else {
p = get_cursor_line_ptr();
validate_virtcol();
- col_print((char *)buf1, sizeof(buf1), (int)curwin->w_cursor.col + 1,
+ col_print(buf1, sizeof(buf1), (int)curwin->w_cursor.col + 1,
(int)curwin->w_virtcol + 1);
col_print((char *)buf2, sizeof(buf2), (int)strlen(p), linetabsize(p));
@@ -5500,7 +5509,7 @@ void cursor_pos_info(dict_T *dict)
_("Col %s of %s; Line %" PRId64 " of %" PRId64 ";"
" Word %" PRId64 " of %" PRId64 ";"
" Byte %" PRId64 " of %" PRId64 ""),
- (char *)buf1, (char *)buf2,
+ buf1, buf2,
(int64_t)curwin->w_cursor.lnum,
(int64_t)curbuf->b_ml.ml_line_count,
(int64_t)word_count_cursor, (int64_t)word_count,
@@ -5511,7 +5520,7 @@ void cursor_pos_info(dict_T *dict)
" Word %" PRId64 " of %" PRId64 ";"
" Char %" PRId64 " of %" PRId64 ";"
" Byte %" PRId64 " of %" PRId64 ""),
- (char *)buf1, (char *)buf2,
+ buf1, buf2,
(int64_t)curwin->w_cursor.lnum,
(int64_t)curbuf->b_ml.ml_line_count,
(int64_t)word_count_cursor, (int64_t)word_count,
@@ -5617,10 +5626,11 @@ static void op_colon(oparg_T *oap)
static Callback opfunc_cb;
/// Process the 'operatorfunc' option value.
-/// @return OK or FAIL
-int set_operatorfunc_option(void)
+void set_operatorfunc_option(char **errmsg)
{
- return option_set_callback_func(p_opfunc, &opfunc_cb);
+ if (option_set_callback_func(p_opfunc, &opfunc_cb) == FAIL) {
+ *errmsg = e_invarg;
+ }
}
#if defined(EXITFREE)
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 02c770e608..387b94533c 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -36,6 +36,7 @@
#include "nvim/buffer.h"
#include "nvim/change.h"
#include "nvim/charset.h"
+#include "nvim/cmdexpand.h"
#include "nvim/cursor_shape.h"
#include "nvim/decoration_provider.h"
#include "nvim/diff.h"
@@ -81,6 +82,7 @@
#include "nvim/regexp.h"
#include "nvim/runtime.h"
#include "nvim/screen.h"
+#include "nvim/search.h"
#include "nvim/sign_defs.h"
#include "nvim/spell.h"
#include "nvim/spellfile.h"
@@ -173,8 +175,6 @@ void set_init_tablocal(void)
/// editor state initialized here. Do logging in set_init_2 or later.
void set_init_1(bool clean_arg)
{
- int opt_idx;
-
langmap_init();
// Find default value for 'shell' option.
@@ -202,7 +202,7 @@ void set_init_1(bool clean_arg)
static char *(names[3]) = { "TMPDIR", "TEMP", "TMP" };
#endif
garray_T ga;
- opt_idx = findoption("backupskip");
+ int opt_idx = findoption("backupskip");
ga_init(&ga, 1, 100);
for (size_t n = 0; n < ARRAY_SIZE(names); n++) {
@@ -251,19 +251,14 @@ void set_init_1(bool clean_arg)
}
{
- char *cdpath;
- char *buf;
- int i;
- int j;
-
// Initialize the 'cdpath' option's default value.
- cdpath = vim_getenv("CDPATH");
+ char *cdpath = vim_getenv("CDPATH");
if (cdpath != NULL) {
- buf = xmalloc(2 * strlen(cdpath) + 2);
+ char *buf = xmalloc(2 * strlen(cdpath) + 2);
{
buf[0] = ','; // start with ",", current dir first
- j = 1;
- for (i = 0; cdpath[i] != NUL; i++) {
+ int j = 1;
+ for (int i = 0; cdpath[i] != NUL; i++) {
if (vim_ispathlistsep(cdpath[i])) {
buf[j++] = ',';
} else {
@@ -274,7 +269,7 @@ void set_init_1(bool clean_arg)
}
}
buf[j] = NUL;
- opt_idx = findoption("cdpath");
+ int opt_idx = findoption("cdpath");
if (opt_idx >= 0) {
options[opt_idx].def_val = buf;
options[opt_idx].flags |= P_DEF_ALLOCED;
@@ -339,25 +334,25 @@ void set_init_1(bool clean_arg)
// them.
// Don't set the P_ALLOCED flag, because we don't want to free the
// default.
- for (opt_idx = 0; options[opt_idx].fullname; opt_idx++) {
- if (options[opt_idx].flags & P_NO_DEF_EXP) {
+ for (int opt_idx = 0; options[opt_idx].fullname; opt_idx++) {
+ vimoption_T *opt = &options[opt_idx];
+ if (opt->flags & P_NO_DEF_EXP) {
continue;
}
char *p;
- if ((options[opt_idx].flags & P_GETTEXT)
- && options[opt_idx].var != NULL) {
- p = _(*(char **)options[opt_idx].var);
+ if ((opt->flags & P_GETTEXT) && opt->var != NULL) {
+ p = _(*(char **)opt->var);
} else {
p = option_expand(opt_idx, NULL);
}
if (p != NULL) {
p = xstrdup(p);
- *(char **)options[opt_idx].var = p;
- if (options[opt_idx].flags & P_DEF_ALLOCED) {
- xfree(options[opt_idx].def_val);
+ *(char **)opt->var = p;
+ if (opt->flags & P_DEF_ALLOCED) {
+ xfree(opt->def_val);
}
- options[opt_idx].def_val = p;
- options[opt_idx].flags |= P_DEF_ALLOCED;
+ opt->def_val = p;
+ opt->flags |= P_DEF_ALLOCED;
}
}
@@ -379,12 +374,12 @@ void set_init_1(bool clean_arg)
// enc_locale() will try to find the encoding of the current locale.
// This will be used when 'default' is used as encoding specifier
// in 'fileencodings'
- char_u *p = enc_locale();
+ char *p = enc_locale();
if (p == NULL) {
// use utf-8 as 'default' if locale encoding can't be detected.
- p = (char_u *)xmemdupz(S_LEN("utf-8"));
+ p = xmemdupz(S_LEN("utf-8"));
}
- fenc_default = (char *)p;
+ fenc_default = p;
#ifdef HAVE_WORKING_LIBINTL
// GNU gettext 0.10.37 supports this feature: set the codeset used for
@@ -400,32 +395,32 @@ void set_init_1(bool clean_arg)
/// This does not take care of side effects!
///
/// @param opt_flags OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL
-static void set_option_default(int opt_idx, int opt_flags)
+static void set_option_default(const int opt_idx, int opt_flags)
{
- char_u *varp; // pointer to variable for current option
int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
- varp = (char_u *)get_varp_scope(&(options[opt_idx]), both ? OPT_LOCAL : opt_flags);
- uint32_t flags = options[opt_idx].flags;
+ // pointer to variable for current option
+ vimoption_T *opt = &options[opt_idx];
+ char_u *varp = (char_u *)get_varp_scope(opt, both ? OPT_LOCAL : opt_flags);
+ uint32_t flags = opt->flags;
if (varp != NULL) { // skip hidden option, nothing to do for it
if (flags & P_STRING) {
// Use set_string_option_direct() for local options to handle
// freeing and allocating the value.
- if (options[opt_idx].indir != PV_NONE) {
- set_string_option_direct(NULL, opt_idx,
- options[opt_idx].def_val, opt_flags, 0);
+ if (opt->indir != PV_NONE) {
+ set_string_option_direct(NULL, opt_idx, opt->def_val, opt_flags, 0);
} else {
if ((opt_flags & OPT_FREE) && (flags & P_ALLOCED)) {
free_string_option(*(char **)(varp));
}
- *(char **)varp = options[opt_idx].def_val;
- options[opt_idx].flags &= ~P_ALLOCED;
+ *(char **)varp = opt->def_val;
+ opt->flags &= ~P_ALLOCED;
}
} else if (flags & P_NUM) {
- if (options[opt_idx].indir == PV_SCROLL) {
+ if (opt->indir == PV_SCROLL) {
win_comp_scroll(curwin);
} else {
- long def_val = (long)options[opt_idx].def_val;
+ long def_val = (long)opt->def_val;
if ((long *)varp == &curwin->w_p_so
|| (long *)varp == &curwin->w_p_siso) {
// 'scrolloff' and 'sidescrolloff' local values have a
@@ -436,21 +431,21 @@ static void set_option_default(int opt_idx, int opt_flags)
}
// May also set global value for local option.
if (both) {
- *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) =
+ *(long *)get_varp_scope(opt, OPT_GLOBAL) =
def_val;
}
}
} else { // P_BOOL
- *(int *)varp = (int)(intptr_t)options[opt_idx].def_val;
+ *(int *)varp = (int)(intptr_t)opt->def_val;
#ifdef UNIX
// 'modeline' defaults to off for root
- if (options[opt_idx].indir == PV_ML && getuid() == ROOT_UID) {
+ if (opt->indir == PV_ML && getuid() == ROOT_UID) {
*(int *)varp = false;
}
#endif
// May also set global value for local option.
if (both) {
- *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL) =
+ *(int *)get_varp_scope(opt, OPT_GLOBAL) =
*(int *)varp;
}
}
@@ -493,12 +488,13 @@ static void set_string_default(const char *name, char *val, bool allocated)
{
int opt_idx = findoption(name);
if (opt_idx >= 0) {
- if (options[opt_idx].flags & P_DEF_ALLOCED) {
- xfree(options[opt_idx].def_val);
+ vimoption_T *opt = &options[opt_idx];
+ if (opt->flags & P_DEF_ALLOCED) {
+ xfree(opt->def_val);
}
- options[opt_idx].def_val = allocated ? val : xstrdup(val);
- options[opt_idx].flags |= P_DEF_ALLOCED;
+ opt->def_val = allocated ? val : xstrdup(val);
+ opt->flags |= P_DEF_ALLOCED;
}
}
@@ -507,12 +503,12 @@ static void set_string_default(const char *name, char *val, bool allocated)
static char *find_dup_item(char *origval, const char *newval, uint32_t flags)
FUNC_ATTR_NONNULL_ARG(2)
{
- int bs = 0;
-
if (origval == NULL) {
return NULL;
}
+ int bs = 0;
+
const size_t newlen = strlen(newval);
for (char *s = origval; *s != NUL; s++) {
if ((!(flags & P_COMMA) || s == origval || (s[-1] == ',' && !(bs & 1)))
@@ -572,11 +568,9 @@ void set_init_2(bool headless)
// set in set_init_1 but logging is not allowed there
ILOG("startup runtimepath/packpath value: %s", p_rtp);
- int idx;
-
// 'scroll' defaults to half the window height. The stored default is zero,
// which results in the actual value computed from the window height.
- idx = findoption("scroll");
+ int idx = findoption("scroll");
if (idx >= 0 && !(options[idx].flags & P_WAS_SET)) {
set_option_default(idx, OPT_LOCAL);
}
@@ -674,23 +668,25 @@ void set_helplang_default(const char *lang)
return;
}
int idx = findoption("hlg");
- if (idx >= 0 && !(options[idx].flags & P_WAS_SET)) {
- if (options[idx].flags & P_ALLOCED) {
- free_string_option(p_hlg);
- }
- p_hlg = xmemdupz(lang, lang_len);
- // zh_CN becomes "cn", zh_TW becomes "tw".
- if (STRNICMP(p_hlg, "zh_", 3) == 0 && strlen(p_hlg) >= 5) {
- p_hlg[0] = (char)TOLOWER_ASC(p_hlg[3]);
- p_hlg[1] = (char)TOLOWER_ASC(p_hlg[4]);
- } else if (strlen(p_hlg) >= 1 && *p_hlg == 'C') {
- // any C like setting, such as C.UTF-8, becomes "en"
- p_hlg[0] = 'e';
- p_hlg[1] = 'n';
- }
- p_hlg[2] = NUL;
- options[idx].flags |= P_ALLOCED;
+ if (idx < 0 || (options[idx].flags & P_WAS_SET)) {
+ return;
+ }
+
+ if (options[idx].flags & P_ALLOCED) {
+ free_string_option(p_hlg);
}
+ p_hlg = xmemdupz(lang, lang_len);
+ // zh_CN becomes "cn", zh_TW becomes "tw".
+ if (STRNICMP(p_hlg, "zh_", 3) == 0 && strlen(p_hlg) >= 5) {
+ p_hlg[0] = (char)TOLOWER_ASC(p_hlg[3]);
+ p_hlg[1] = (char)TOLOWER_ASC(p_hlg[4]);
+ } else if (strlen(p_hlg) >= 1 && *p_hlg == 'C') {
+ // any C like setting, such as C.UTF-8, becomes "en"
+ p_hlg[0] = 'e';
+ p_hlg[1] = 'n';
+ }
+ p_hlg[2] = NUL;
+ options[idx].flags |= P_ALLOCED;
}
/// 'title' and 'icon' only default to true if they have not been set or reset
@@ -730,25 +726,181 @@ void ex_set(exarg_T *eap)
(void)do_set(eap->arg, flags);
}
+static void do_set_bool(int opt_idx, int opt_flags, int prefix, int nextchar, const char *varp,
+ char **errmsg)
+{
+ varnumber_T value;
+
+ // ":set opt!": invert
+ // ":set opt&": reset to default value
+ // ":set opt<": reset to global value
+ if (nextchar == '!') {
+ value = *(int *)(varp) ^ 1;
+ } else if (nextchar == '&') {
+ value = (int)(intptr_t)options[opt_idx].def_val;
+ } else if (nextchar == '<') {
+ // For 'autoread' -1 means to use global value.
+ if ((int *)varp == &curbuf->b_p_ar && opt_flags == OPT_LOCAL) {
+ value = -1;
+ } else {
+ value = *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
+ }
+ } else {
+ if (prefix == 2) {
+ value = *(int *)varp ^ 1; // ":set invopt": invert
+ } else {
+ value = prefix; // ":set opt" or ":set noopt": set or reset
+ }
+ }
+
+ *errmsg = set_bool_option(opt_idx, (char_u *)varp, (int)value, opt_flags);
+}
+
+static void do_set_num(int opt_idx, int opt_flags, char **argp, int nextchar, const set_op_T op,
+ const char *varp, char *errbuf, size_t errbuflen, char **errmsg)
+{
+ varnumber_T value;
+ char *arg = *argp;
+
+ // Different ways to set a number option:
+ // & set to default value
+ // < set to global value
+ // <xx> accept special key codes for 'wildchar'
+ // c accept any non-digit for 'wildchar'
+ // [-]0-9 set number
+ // other error
+ arg++;
+ if (nextchar == '&') {
+ value = (long)(intptr_t)options[opt_idx].def_val;
+ } else if (nextchar == '<') {
+ // For 'undolevels' NO_LOCAL_UNDOLEVEL means to
+ // use the global value.
+ if ((long *)varp == &curbuf->b_p_ul && opt_flags == OPT_LOCAL) {
+ value = NO_LOCAL_UNDOLEVEL;
+ } else {
+ value = *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
+ }
+ } else if (((long *)varp == &p_wc
+ || (long *)varp == &p_wcm)
+ && (*arg == '<'
+ || *arg == '^'
+ || (*arg != NUL && (!arg[1] || ascii_iswhite(arg[1]))
+ && !ascii_isdigit(*arg)))) {
+ value = string_to_key(arg);
+ if (value == 0 && (long *)varp != &p_wcm) {
+ *errmsg = e_invarg;
+ return;
+ }
+ } else if (*arg == '-' || ascii_isdigit(*arg)) {
+ int i;
+ // Allow negative, octal and hex numbers.
+ vim_str2nr(arg, NULL, &i, STR2NR_ALL, &value, NULL, 0, true);
+ if (i == 0 || (arg[i] != NUL && !ascii_iswhite(arg[i]))) {
+ *errmsg = e_number_required_after_equal;
+ return;
+ }
+ } else {
+ *errmsg = e_number_required_after_equal;
+ return;
+ }
+
+ if (op == OP_ADDING) {
+ value = *(long *)varp + value;
+ }
+ if (op == OP_PREPENDING) {
+ value = *(long *)varp * value;
+ }
+ if (op == OP_REMOVING) {
+ value = *(long *)varp - value;
+ }
+ *errmsg = set_num_option(opt_idx, (char_u *)varp, (long)value,
+ errbuf, errbuflen, opt_flags);
+}
+
+// Handle some special cases with string option values
+static void munge_string_opt_val(char **varp, char **oldval, char **const origval,
+ char_u **const origval_l, char_u **const origval_g,
+ char **const argp, char *const whichwrap, size_t whichwraplen,
+ char **const save_argp)
+{
+ // Set 'keywordprg' to ":help" if an empty
+ // value was passed to :set by the user.
+ if (varp == &p_kp && (**argp == NUL || **argp == ' ')) {
+ *save_argp = *argp;
+ *argp = ":help";
+ } else if (varp == &p_bs && ascii_isdigit(**(char_u **)varp)) {
+ // Convert 'backspace' number to string, for
+ // adding, prepending and removing string.
+ const int i = getdigits_int(varp, true, 0);
+ switch (i) {
+ case 0:
+ *varp = empty_option;
+ break;
+ case 1:
+ *varp = xstrdup("indent,eol");
+ break;
+ case 2:
+ *varp = xstrdup("indent,eol,start");
+ break;
+ case 3:
+ *varp = xstrdup("indent,eol,nostop");
+ break;
+ }
+ xfree(*oldval);
+ if (*origval == *oldval) {
+ *origval = *varp;
+ }
+ if (*origval_l == (char_u *)(*oldval)) {
+ *origval_l = *(char_u **)varp;
+ }
+ if (*origval_g == (char_u *)(*oldval)) {
+ *origval_g = *(char_u **)varp;
+ }
+ *oldval = *varp;
+ } else if (varp == &p_ww && ascii_isdigit(**argp)) {
+ // Convert 'whichwrap' number to string, for backwards compatibility
+ // with Vim 3.0.
+ *whichwrap = NUL;
+ int i = getdigits_int(argp, true, 0);
+ if (i & 1) {
+ xstrlcat(whichwrap, "b,", whichwraplen);
+ }
+ if (i & 2) {
+ xstrlcat(whichwrap, "s,", whichwraplen);
+ }
+ if (i & 4) {
+ xstrlcat(whichwrap, "h,l,", whichwraplen);
+ }
+ if (i & 8) {
+ xstrlcat(whichwrap, "<,>,", whichwraplen);
+ }
+ if (i & 16) {
+ xstrlcat(whichwrap, "[,],", whichwraplen);
+ }
+ if (*whichwrap != NUL) { // remove trailing ,
+ whichwrap[strlen(whichwrap) - 1] = NUL;
+ }
+ *save_argp = *argp;
+ *argp = whichwrap;
+ } else if (**argp == '>' && (varp == &p_dir || varp == &p_bdir)) {
+ // Remove '>' before 'dir' and 'bdir', for backwards compatibility with
+ // version 3.0
+ (*argp)++;
+ }
+}
+
/// Part of do_set() for string options.
-/// @return FAIL on failure, do not process further options.
-static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, set_op_T op_arg,
- uint32_t flags, char *varp_arg, char *errbuf, size_t errbuflen,
- int *value_checked, char **errmsg)
+static void do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar, set_op_T op_arg,
+ uint32_t flags, char *varp_arg, char *errbuf, size_t errbuflen,
+ int *value_checked, char **errmsg)
{
char *arg = *argp;
set_op_T op = op_arg;
char *varp = varp_arg;
char *save_arg = NULL;
char *s = NULL;
- char *oldval = NULL; // previous value if *varp
- char *origval = NULL;
char_u *origval_l = NULL;
char_u *origval_g = NULL;
- char *saved_origval = NULL;
- char *saved_origval_l = NULL;
- char *saved_origval_g = NULL;
- char *saved_newval = NULL;
char whichwrap[80];
// When using ":set opt=val" for a global option
@@ -760,7 +912,7 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar,
}
// The old value is kept until we are sure that the new value is valid.
- oldval = *(char **)varp;
+ char *oldval = *(char **)varp;
if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) {
origval_l = *(char_u **)get_varp_scope(&(options[opt_idx]), OPT_LOCAL);
@@ -773,6 +925,7 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar,
}
}
+ char *origval;
// When setting the local value of a global option, the old value may be
// the global value.
if (((int)options[opt_idx].indir & PV_BOTH) && (opt_flags & OPT_LOCAL)) {
@@ -803,70 +956,8 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar,
} else {
arg++; // jump to after the '=' or ':'
- // Set 'keywordprg' to ":help" if an empty
- // value was passed to :set by the user.
- if (varp == (char *)&p_kp && (*arg == NUL || *arg == ' ')) {
- save_arg = arg;
- arg = ":help";
- } else if (varp == (char *)&p_bs && ascii_isdigit(**(char_u **)varp)) {
- // Convert 'backspace' number to string, for
- // adding, prepending and removing string.
- int i = getdigits_int((char **)varp, true, 0);
- switch (i) {
- case 0:
- *(char **)varp = empty_option;
- break;
- case 1:
- *(char_u **)varp = (char_u *)xstrdup("indent,eol");
- break;
- case 2:
- *(char_u **)varp = (char_u *)xstrdup("indent,eol,start");
- break;
- case 3:
- *(char_u **)varp = (char_u *)xstrdup("indent,eol,nostop");
- break;
- }
- xfree(oldval);
- if (origval == oldval) {
- origval = *(char **)varp;
- }
- if (origval_l == (char_u *)oldval) {
- origval_l = *(char_u **)varp;
- }
- if (origval_g == (char_u *)oldval) {
- origval_g = *(char_u **)varp;
- }
- oldval = *(char **)varp;
- } else if (varp == (char *)&p_ww && ascii_isdigit(*arg)) {
- // Convert 'whichwrap' number to string, for backwards compatibility
- // with Vim 3.0.
- *whichwrap = NUL;
- int i = getdigits_int(&arg, true, 0);
- if (i & 1) {
- xstrlcat(whichwrap, "b,", sizeof(whichwrap));
- }
- if (i & 2) {
- xstrlcat(whichwrap, "s,", sizeof(whichwrap));
- }
- if (i & 4) {
- xstrlcat(whichwrap, "h,l,", sizeof(whichwrap));
- }
- if (i & 8) {
- xstrlcat(whichwrap, "<,>,", sizeof(whichwrap));
- }
- if (i & 16) {
- xstrlcat(whichwrap, "[,],", sizeof(whichwrap));
- }
- if (*whichwrap != NUL) { // remove trailing ,
- whichwrap[strlen(whichwrap) - 1] = NUL;
- }
- save_arg = arg;
- arg = whichwrap;
- } else if (*arg == '>' && (varp == (char *)&p_dir || varp == (char *)&p_bdir)) {
- // Remove '>' before 'dir' and 'bdir', for backwards compatibility with
- // version 3.0
- arg++;
- }
+ munge_string_opt_val((char **)varp, &oldval, &origval, &origval_l, &origval_g, &arg,
+ whichwrap, sizeof(whichwrap), &save_arg);
// Copy the new string into allocated memory.
// Can't use set_string_option_direct(), because we need to remove the
@@ -995,14 +1086,14 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar,
// 'whichwrap'
if (flags & P_ONECOMMA) {
if (*s != ',' && *(s + 1) == ','
- && vim_strchr(s + 2, *s) != NULL) {
+ && vim_strchr(s + 2, (uint8_t)(*s)) != NULL) {
// Remove the duplicated value and the next comma.
STRMOVE(s, s + 2);
continue;
}
} else {
if ((!(flags & P_COMMA) || *s != ',')
- && vim_strchr(s + 1, *s) != NULL) {
+ && vim_strchr(s + 1, (uint8_t)(*s)) != NULL) {
STRMOVE(s, s + 1);
continue;
}
@@ -1020,13 +1111,13 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar,
*(char_u **)(varp) = (char_u *)newval;
// origval may be freed by did_set_string_option(), make a copy.
- saved_origval = (origval != NULL) ? xstrdup(origval) : NULL;
- saved_origval_l = (origval_l != NULL) ? xstrdup((char *)origval_l) : NULL;
- saved_origval_g = (origval_g != NULL) ? xstrdup((char *)origval_g) : NULL;
+ char *saved_origval = (origval != NULL) ? xstrdup(origval) : NULL;
+ char *saved_origval_l = (origval_l != NULL) ? xstrdup((char *)origval_l) : NULL;
+ char *saved_origval_g = (origval_g != NULL) ? xstrdup((char *)origval_g) : NULL;
// newval (and varp) may become invalid if the buffer is closed by
// autocommands.
- saved_newval = (newval != NULL) ? xstrdup(newval) : NULL;
+ char *saved_newval = (newval != NULL) ? xstrdup(newval) : NULL;
{
uint32_t *p = insecure_flag(curwin, opt_idx, opt_flags);
@@ -1068,416 +1159,391 @@ static int do_set_string(int opt_idx, int opt_flags, char **argp, int nextchar,
xfree(saved_newval);
*argp = arg;
- return *errmsg == NULL ? OK : FAIL;
}
-/// Parse 'arg' for option settings.
-///
-/// 'arg' may be IObuff, but only when no errors can be present and option
-/// does not need to be expanded with option_expand().
-/// "opt_flags":
-/// 0 for ":set"
-/// OPT_GLOBAL for ":setglobal"
-/// OPT_LOCAL for ":setlocal" and a modeline
-/// OPT_MODELINE for a modeline
-/// OPT_WINONLY to only set window-local options
-/// OPT_NOWIN to skip setting window-local options
-///
-/// @param arg option string (may be written to!)
-///
+static set_op_T get_op(const char *arg)
+{
+ set_op_T op = OP_NONE;
+ if (*arg != NUL && *(arg + 1) == '=') {
+ if (*arg == '+') {
+ op = OP_ADDING; // "+="
+ } else if (*arg == '^') {
+ op = OP_PREPENDING; // "^="
+ } else if (*arg == '-') {
+ op = OP_REMOVING; // "-="
+ }
+ }
+ return op;
+}
+
+static int get_option_prefix(char **argp)
+{
+ if (strncmp(*argp, "no", 2) == 0) {
+ *argp += 2;
+ return 0;
+ } else if (strncmp(*argp, "inv", 3) == 0) {
+ *argp += 3;
+ return 2;
+ }
+
+ return 1;
+}
+
+/// @param[in] arg Pointer to start option name
+/// @param[out] opt_idxp Option index in options[] table.
+/// @param[out] keyp
+/// @param[out] len Length of option name
/// @return FAIL if an error is detected, OK otherwise
-int do_set(char *arg, int opt_flags)
+static int parse_option_name(char *arg, int *keyp, int *lenp, int *opt_idxp)
{
- int did_show = false; // already showed one value
+ // find end of name
+ int key = 0;
+ int len;
+ int opt_idx;
- if (*arg == NUL) {
- showoptions(0, opt_flags);
- did_show = true;
- goto theend;
- }
-
- char errbuf[80];
-
- while (*arg != NUL) { // loop to process all options
- char *errmsg = NULL;
- char *startarg = arg; // remember for error message
-
- if (strncmp(arg, "all", 3) == 0 && !isalpha(arg[3])
- && !(opt_flags & OPT_MODELINE)) {
- // ":set all" show all options.
- // ":set all&" set all options to their default value.
- arg += 3;
- if (*arg == '&') {
- arg++;
- // Only for :set command set global value of local options.
- set_options_default(OPT_FREE | opt_flags);
- didset_options();
- didset_options2();
- ui_refresh_options();
- redraw_all_later(UPD_CLEAR);
- } else {
- showoptions(1, opt_flags);
- did_show = true;
- }
+ if (*arg == '<') {
+ opt_idx = -1;
+ // look out for <t_>;>
+ if (arg[1] == 't' && arg[2] == '_' && arg[3] && arg[4]) {
+ len = 5;
} else {
- int prefix = 1; // 1: nothing, 0: "no", 2: "inv" in front of name
- if (strncmp(arg, "no", 2) == 0) {
- prefix = 0;
- arg += 2;
- } else if (strncmp(arg, "inv", 3) == 0) {
- prefix = 2;
- arg += 3;
+ len = 1;
+ while (arg[len] != NUL && arg[len] != '>') {
+ len++;
}
-
- // find end of name
- int key = 0;
- int len;
- int opt_idx;
- if (*arg == '<') {
- opt_idx = -1;
- // look out for <t_>;>
- if (arg[1] == 't' && arg[2] == '_' && arg[3] && arg[4]) {
- len = 5;
- } else {
- len = 1;
- while (arg[len] != NUL && arg[len] != '>') {
- len++;
- }
- }
- if (arg[len] != '>') {
- errmsg = e_invarg;
- goto skip;
- }
- if (arg[1] == 't' && arg[2] == '_') { // could be term code
- opt_idx = findoption_len((const char *)arg + 1, (size_t)(len - 1));
- }
+ }
+ if (arg[len] != '>') {
+ return FAIL;
+ }
+ if (arg[1] == 't' && arg[2] == '_') { // could be term code
+ opt_idx = findoption_len((const char *)arg + 1, (size_t)(len - 1));
+ }
+ len++;
+ if (opt_idx == -1) {
+ key = find_key_option(arg + 1, true);
+ }
+ } else {
+ // The two characters after "t_" may not be alphanumeric.
+ if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3]) {
+ len = 4;
+ } else {
+ len = 0;
+ while (ASCII_ISALNUM(arg[len]) || arg[len] == '_') {
len++;
- if (opt_idx == -1) {
- key = find_key_option(arg + 1, true);
- }
- } else {
- len = 0;
- // The two characters after "t_" may not be alphanumeric.
- if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3]) {
- len = 4;
- } else {
- while (ASCII_ISALNUM(arg[len]) || arg[len] == '_') {
- len++;
- }
- }
- opt_idx = findoption_len((const char *)arg, (size_t)len);
- if (opt_idx == -1) {
- key = find_key_option(arg, false);
- }
}
+ }
+ opt_idx = findoption_len((const char *)arg, (size_t)len);
+ if (opt_idx == -1) {
+ key = find_key_option(arg, false);
+ }
+ }
- // remember character after option name
- int afterchar = (uint8_t)arg[len];
+ *keyp = key;
+ *lenp = len;
+ *opt_idxp = opt_idx;
- // skip white space, allow ":set ai ?"
- while (ascii_iswhite(arg[len])) {
- len++;
- }
+ return OK;
+}
- set_op_T op = OP_NONE;
- if (arg[len] != NUL && arg[len + 1] == '=') {
- if (arg[len] == '+') {
- op = OP_ADDING; // "+="
- len++;
- } else if (arg[len] == '^') {
- op = OP_PREPENDING; // "^="
- len++;
- } else if (arg[len] == '-') {
- op = OP_REMOVING; // "-="
- len++;
- }
- }
- char_u nextchar = (uint8_t)arg[len]; // next non-white char after option name
+static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t flags, int prefix,
+ char **errmsg)
+{
+ // Only bools can have a prefix of 'inv' or 'no'
+ if (!(flags & P_BOOL) && prefix != 1) {
+ *errmsg = e_invarg;
+ return FAIL;
+ }
- if (opt_idx == -1 && key == 0) { // found a mismatch: skip
- errmsg = e_unknown_option;
- goto skip;
- }
+ // Skip all options that are not window-local (used when showing
+ // an already loaded buffer in a window).
+ if ((opt_flags & OPT_WINONLY)
+ && (opt_idx < 0 || options[opt_idx].var != VAR_WIN)) {
+ return FAIL;
+ }
- uint32_t flags; // flags for current option
- char *varp = NULL; // pointer to variable for current option
-
- if (opt_idx >= 0) {
- if (options[opt_idx].var == NULL) { // hidden option: skip
- // Only give an error message when requesting the value of
- // a hidden option, ignore setting it.
- if (vim_strchr("=:!&<", nextchar) == NULL
- && (!(options[opt_idx].flags & P_BOOL)
- || nextchar == '?')) {
- errmsg = e_unsupportedoption;
- }
- goto skip;
- }
+ // Skip all options that are window-local (used for :vimgrep).
+ if ((opt_flags & OPT_NOWIN) && opt_idx >= 0
+ && options[opt_idx].var == VAR_WIN) {
+ return FAIL;
+ }
- flags = options[opt_idx].flags;
- varp = get_varp_scope(&(options[opt_idx]), opt_flags);
- } else {
- flags = P_STRING;
- }
+ // Disallow changing some options from modelines.
+ if (opt_flags & OPT_MODELINE) {
+ if (flags & (P_SECURE | P_NO_ML)) {
+ *errmsg = e_not_allowed_in_modeline;
+ return FAIL;
+ }
+ if ((flags & P_MLE) && !p_mle) {
+ *errmsg = e_not_allowed_in_modeline_when_modelineexpr_is_off;
+ return FAIL;
+ }
+ // In diff mode some options are overruled. This avoids that
+ // 'foldmethod' becomes "marker" instead of "diff" and that
+ // "wrap" gets set.
+ if (win->w_p_diff
+ && opt_idx >= 0 // shut up coverity warning
+ && (options[opt_idx].indir == PV_FDM
+ || options[opt_idx].indir == PV_WRAP)) {
+ return FAIL;
+ }
+ }
- // Skip all options that are not window-local (used when showing
- // an already loaded buffer in a window).
- if ((opt_flags & OPT_WINONLY)
- && (opt_idx < 0 || options[opt_idx].var != VAR_WIN)) {
- goto skip;
- }
+ // Disallow changing some options in the sandbox
+ if (sandbox != 0 && (flags & P_SECURE)) {
+ *errmsg = e_sandbox;
+ return FAIL;
+ }
- // Skip all options that are window-local (used for :vimgrep).
- if ((opt_flags & OPT_NOWIN) && opt_idx >= 0
- && options[opt_idx].var == VAR_WIN) {
- goto skip;
- }
+ return OK;
+}
- // Disallow changing some options from modelines.
- if (opt_flags & OPT_MODELINE) {
- if (flags & (P_SECURE | P_NO_ML)) {
- errmsg = e_not_allowed_in_modeline;
- goto skip;
- }
- if ((flags & P_MLE) && !p_mle) {
- errmsg = e_not_allowed_in_modeline_when_modelineexpr_is_off;
- goto skip;
- }
- // In diff mode some options are overruled. This avoids that
- // 'foldmethod' becomes "marker" instead of "diff" and that
- // "wrap" gets set.
- if (curwin->w_p_diff
- && opt_idx >= 0 // shut up coverity warning
- && (options[opt_idx].indir == PV_FDM
- || options[opt_idx].indir == PV_WRAP)) {
- goto skip;
- }
- }
+static void do_set_option_value(int opt_idx, int opt_flags, char **argp, int prefix, int nextchar,
+ set_op_T op, uint32_t flags, char *varp, char *errbuf,
+ size_t errbuflen, char **errmsg)
+{
+ int value_checked = false;
+ if (flags & P_BOOL) { // boolean
+ do_set_bool(opt_idx, opt_flags, prefix, nextchar, varp, errmsg);
+ } else if (flags & P_NUM) { // numeric
+ do_set_num(opt_idx, opt_flags, argp, nextchar, op, varp, errbuf, errbuflen, errmsg);
+ } else if (opt_idx >= 0) { // string.
+ do_set_string(opt_idx, opt_flags, argp, nextchar, op, flags, varp, errbuf,
+ errbuflen, &value_checked, errmsg);
+ } else {
+ // key code option(FIXME(tarruda): Show a warning or something
+ // similar)
+ }
- // Disallow changing some options in the sandbox
- if (sandbox != 0 && (flags & P_SECURE)) {
- errmsg = e_sandbox;
- goto skip;
- }
+ if (*errmsg != NULL) {
+ return;
+ }
- if (vim_strchr("?=:!&<", nextchar) != NULL) {
- arg += len;
- if (nextchar == '&' && arg[1] == 'v' && arg[2] == 'i') {
- if (arg[3] == 'm') { // "opt&vim": set to Vim default
- arg += 3;
- } else { // "opt&vi": set to Vi default
- arg += 2;
- }
- }
- if (vim_strchr("?!&<", nextchar) != NULL
- && arg[1] != NUL && !ascii_iswhite(arg[1])) {
- errmsg = e_trailing;
- goto skip;
- }
- }
+ if (opt_idx >= 0) {
+ did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked);
+ }
+}
- //
- // allow '=' and ':' as MS-DOS command.com allows only one
- // '=' character per "set" command line. grrr. (jw)
- //
- if (nextchar == '?'
- || (prefix == 1
- && vim_strchr("=:&<", nextchar) == NULL
- && !(flags & P_BOOL))) {
- // print value
- if (did_show) {
- msg_putchar('\n'); // cursor below last one
- } else {
- gotocmdline(true); // cursor at status line
- did_show = true; // remember that we did a line
- }
- if (opt_idx >= 0) {
- showoneopt(&options[opt_idx], opt_flags);
- if (p_verbose > 0) {
- // Mention where the option was last set.
- if (varp == (char *)options[opt_idx].var) {
- option_last_set_msg(options[opt_idx].last_set);
- } else if ((int)options[opt_idx].indir & PV_WIN) {
- option_last_set_msg(curwin->w_p_script_ctx[
- (int)options[opt_idx].indir & PV_MASK]);
- } else if ((int)options[opt_idx].indir & PV_BUF) {
- option_last_set_msg(curbuf->b_p_script_ctx[
- (int)options[opt_idx].indir & PV_MASK]);
- }
- }
- } else {
- errmsg = e_key_code_not_set;
- goto skip;
- }
- if (nextchar != '?'
- && nextchar != NUL && !ascii_iswhite(afterchar)) {
- errmsg = e_trailing;
- }
- } else {
- int value_checked = false;
- varnumber_T value;
+static void do_set_option(int opt_flags, char **argp, bool *did_show, char *errbuf,
+ size_t errbuflen, char **errmsg)
+{
+ // 1: nothing, 0: "no", 2: "inv" in front of name
+ int prefix = get_option_prefix(argp);
- if (flags & P_BOOL) { // boolean
- if (nextchar == '=' || nextchar == ':') {
- errmsg = e_invarg;
- goto skip;
- }
+ char *arg = *argp;
- // ":set opt!": invert
- // ":set opt&": reset to default value
- // ":set opt<": reset to global value
- if (nextchar == '!') {
- value = *(int *)(varp) ^ 1;
- } else if (nextchar == '&') {
- value = (int)(intptr_t)options[opt_idx].def_val;
- } else if (nextchar == '<') {
- // For 'autoread' -1 means to use global value.
- if ((int *)varp == &curbuf->b_p_ar
- && opt_flags == OPT_LOCAL) {
- value = -1;
- } else {
- value = *(int *)get_varp_scope(&(options[opt_idx]),
- OPT_GLOBAL);
- }
- } else {
- // ":set invopt": invert
- // ":set opt" or ":set noopt": set or reset
- if (nextchar != NUL && !ascii_iswhite(afterchar)) {
- errmsg = e_trailing;
- goto skip;
- }
- if (prefix == 2) { // inv
- value = *(int *)(varp) ^ 1;
- } else {
- value = prefix;
- }
- }
+ // find end of name
+ int key = 0;
+ int len;
+ int opt_idx;
+ if (parse_option_name(arg, &key, &len, &opt_idx) == FAIL) {
+ *errmsg = e_invarg;
+ return;
+ }
- errmsg = set_bool_option(opt_idx, (char_u *)varp, (int)value, opt_flags);
- } else { // Numeric or string.
- if (vim_strchr("=:&<", nextchar) == NULL
- || prefix != 1) {
- errmsg = e_invarg;
- goto skip;
- }
+ // remember character after option name
+ int afterchar = (uint8_t)arg[len];
- if (flags & P_NUM) { // numeric
- // Different ways to set a number option:
- // & set to default value
- // < set to global value
- // <xx> accept special key codes for 'wildchar'
- // c accept any non-digit for 'wildchar'
- // [-]0-9 set number
- // other error
- arg++;
- if (nextchar == '&') {
- value = (long)(intptr_t)options[opt_idx].def_val;
- } else if (nextchar == '<') {
- // For 'undolevels' NO_LOCAL_UNDOLEVEL means to
- // use the global value.
- if ((long *)varp == &curbuf->b_p_ul && opt_flags == OPT_LOCAL) {
- value = NO_LOCAL_UNDOLEVEL;
- } else {
- value = *(long *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
- }
- } else if (((long *)varp == &p_wc
- || (long *)varp == &p_wcm)
- && (*arg == '<'
- || *arg == '^'
- || (*arg != NUL && (!arg[1] || ascii_iswhite(arg[1]))
- && !ascii_isdigit(*arg)))) {
- value = string_to_key((char_u *)arg);
- if (value == 0 && (long *)varp != &p_wcm) {
- errmsg = e_invarg;
- goto skip;
- }
- } else if (*arg == '-' || ascii_isdigit(*arg)) {
- int i;
- // Allow negative, octal and hex numbers.
- vim_str2nr(arg, NULL, &i, STR2NR_ALL, &value, NULL, 0, true);
- if (i == 0 || (arg[i] != NUL && !ascii_iswhite(arg[i]))) {
- errmsg = e_number_required_after_equal;
- goto skip;
- }
- } else {
- errmsg = e_number_required_after_equal;
- goto skip;
- }
+ // skip white space, allow ":set ai ?"
+ while (ascii_iswhite(arg[len])) {
+ len++;
+ }
- if (op == OP_ADDING) {
- value = *(long *)varp + value;
- }
- if (op == OP_PREPENDING) {
- value = *(long *)varp * value;
- }
- if (op == OP_REMOVING) {
- value = *(long *)varp - value;
- }
- errmsg = set_num_option(opt_idx, (char_u *)varp, (long)value,
- errbuf, sizeof(errbuf),
- opt_flags);
- } else if (opt_idx >= 0) { // String.
- if (do_set_string(opt_idx, opt_flags, &arg, nextchar,
- op, flags, varp, errbuf, sizeof(errbuf),
- &value_checked, &errmsg) == FAIL) {
- if (errmsg != NULL) {
- goto skip;
- }
- break;
- }
- } else {
- // key code option(FIXME(tarruda): Show a warning or something
- // similar)
- }
- }
+ set_op_T op = get_op(arg + len);
+ if (op != OP_NONE) {
+ len++;
+ }
- if (opt_idx >= 0) {
- did_set_option(opt_idx, opt_flags, op == OP_NONE, value_checked);
- }
+ uint8_t nextchar = (uint8_t)arg[len]; // next non-white char after option name
+
+ if (opt_idx == -1 && key == 0) { // found a mismatch: skip
+ *errmsg = e_unknown_option;
+ return;
+ }
+
+ uint32_t flags; // flags for current option
+ char *varp = NULL; // pointer to variable for current option
+
+ if (opt_idx >= 0) {
+ if (options[opt_idx].var == NULL) { // hidden option: skip
+ // Only give an error message when requesting the value of
+ // a hidden option, ignore setting it.
+ if (vim_strchr("=:!&<", nextchar) == NULL
+ && (!(options[opt_idx].flags & P_BOOL)
+ || nextchar == '?')) {
+ *errmsg = e_unsupportedoption;
}
+ return;
+ }
-skip:
- // Advance to next argument.
- // - skip until a blank found, taking care of backslashes
- // - skip blanks
- // - skip one "=val" argument (for hidden options ":set gfn =xx")
- for (int i = 0; i < 2; i++) {
- while (*arg != NUL && !ascii_iswhite(*arg)) {
- if (*arg++ == '\\' && *arg != NUL) {
- arg++;
- }
- }
- arg = skipwhite(arg);
- if (*arg != '=') {
- break;
- }
+ flags = options[opt_idx].flags;
+ varp = get_varp_scope(&(options[opt_idx]), opt_flags);
+ } else {
+ flags = P_STRING;
+ }
+
+ if (validate_opt_idx(curwin, opt_idx, opt_flags, flags, prefix, errmsg) == FAIL) {
+ return;
+ }
+
+ if (vim_strchr("?=:!&<", nextchar) != NULL) {
+ *argp += len;
+ if (nextchar == '&' && (*argp)[1] == 'v' && (*argp)[2] == 'i') {
+ if ((*argp)[3] == 'm') { // "opt&vim": set to Vim default
+ *argp += 3;
+ } else { // "opt&vi": set to Vi default
+ *argp += 2;
}
}
+ if (vim_strchr("?!&<", nextchar) != NULL
+ && (*argp)[1] != NUL && !ascii_iswhite((*argp)[1])) {
+ *errmsg = e_trailing;
+ return;
+ }
+ }
- if (errmsg != NULL) {
- xstrlcpy(IObuff, _(errmsg), IOSIZE);
- int i = (int)strlen(IObuff) + 2;
- if (i + (arg - startarg) < IOSIZE) {
- // append the argument with the error
- STRCAT(IObuff, ": ");
- assert(arg >= startarg);
- memmove(IObuff + i, startarg, (size_t)(arg - startarg));
- IObuff[i + (arg - startarg)] = NUL;
+ //
+ // allow '=' and ':' as MS-DOS command.com allows only one
+ // '=' character per "set" command line. grrr. (jw)
+ //
+ if (nextchar == '?'
+ || (prefix == 1
+ && vim_strchr("=:&<", nextchar) == NULL
+ && !(flags & P_BOOL))) {
+ // print value
+ if (*did_show) {
+ msg_putchar('\n'); // cursor below last one
+ } else {
+ gotocmdline(true); // cursor at status line
+ *did_show = true; // remember that we did a line
+ }
+ if (opt_idx >= 0) {
+ showoneopt(&options[opt_idx], opt_flags);
+ if (p_verbose > 0) {
+ // Mention where the option was last set.
+ if (varp == (char *)options[opt_idx].var) {
+ option_last_set_msg(options[opt_idx].last_set);
+ } else if ((int)options[opt_idx].indir & PV_WIN) {
+ option_last_set_msg(curwin->w_p_script_ctx[(int)options[opt_idx].indir & PV_MASK]);
+ } else if ((int)options[opt_idx].indir & PV_BUF) {
+ option_last_set_msg(curbuf->b_p_script_ctx[(int)options[opt_idx].indir & PV_MASK]);
+ }
}
- // make sure all characters are printable
- trans_characters(IObuff, IOSIZE);
+ } else {
+ *errmsg = e_key_code_not_set;
+ return;
+ }
+ if (nextchar != '?' && nextchar != NUL && !ascii_iswhite(afterchar)) {
+ *errmsg = e_trailing;
+ }
+ return;
+ }
- no_wait_return++; // wait_return() done later
- emsg(IObuff); // show error highlighted
- no_wait_return--;
+ if (flags & P_BOOL) {
+ if (vim_strchr("=:", nextchar) != NULL) {
+ *errmsg = e_invarg;
+ return;
+ }
- return FAIL;
+ if (vim_strchr("!&<", nextchar) == NULL && nextchar != NUL && !ascii_iswhite(afterchar)) {
+ *errmsg = e_trailing;
+ return;
}
+ } else {
+ if (vim_strchr("=:&<", nextchar) == NULL) {
+ *errmsg = e_invarg;
+ return;
+ }
+ }
+
+ do_set_option_value(opt_idx, opt_flags, argp, prefix, nextchar, op, flags, varp,
+ errbuf, errbuflen, errmsg);
+}
+
+/// Parse 'arg' for option settings.
+///
+/// 'arg' may be IObuff, but only when no errors can be present and option
+/// does not need to be expanded with option_expand().
+/// "opt_flags":
+/// 0 for ":set"
+/// OPT_GLOBAL for ":setglobal"
+/// OPT_LOCAL for ":setlocal" and a modeline
+/// OPT_MODELINE for a modeline
+/// OPT_WINONLY to only set window-local options
+/// OPT_NOWIN to skip setting window-local options
+///
+/// @param arg option string (may be written to!)
+///
+/// @return FAIL if an error is detected, OK otherwise
+int do_set(char *arg, int opt_flags)
+{
+ bool did_show = false; // already showed one value
- arg = skipwhite(arg);
+ if (*arg == NUL) {
+ showoptions(false, opt_flags);
+ did_show = true;
+ } else {
+ while (*arg != NUL) { // loop to process all options
+ if (strncmp(arg, "all", 3) == 0 && !ASCII_ISALPHA(arg[3])
+ && !(opt_flags & OPT_MODELINE)) {
+ // ":set all" show all options.
+ // ":set all&" set all options to their default value.
+ arg += 3;
+ if (*arg == '&') {
+ arg++;
+ // Only for :set command set global value of local options.
+ set_options_default(OPT_FREE | opt_flags);
+ didset_options();
+ didset_options2();
+ ui_refresh_options();
+ redraw_all_later(UPD_CLEAR);
+ } else {
+ showoptions(true, opt_flags);
+ did_show = true;
+ }
+ } else {
+ char *startarg = arg; // remember for error message
+ char *errmsg = NULL;
+ char errbuf[80];
+
+ do_set_option(opt_flags, &arg, &did_show, errbuf, sizeof(errbuf), &errmsg);
+
+ // Advance to next argument.
+ // - skip until a blank found, taking care of backslashes
+ // - skip blanks
+ // - skip one "=val" argument (for hidden options ":set gfn =xx")
+ for (int i = 0; i < 2; i++) {
+ arg = skiptowhite_esc(arg);
+ arg = skipwhite(arg);
+ if (*arg != '=') {
+ break;
+ }
+ }
+
+ if (errmsg != NULL) {
+ xstrlcpy(IObuff, _(errmsg), IOSIZE);
+ int i = (int)strlen(IObuff) + 2;
+ if (i + (arg - startarg) < IOSIZE) {
+ // append the argument with the error
+ STRCAT(IObuff, ": ");
+ assert(arg >= startarg);
+ memmove(IObuff + i, startarg, (size_t)(arg - startarg));
+ IObuff[i + (arg - startarg)] = NUL;
+ }
+ // make sure all characters are printable
+ trans_characters(IObuff, IOSIZE);
+
+ no_wait_return++; // wait_return() done later
+ emsg(IObuff); // show error highlighted
+ no_wait_return--;
+
+ return FAIL;
+ }
+ }
+
+ arg = skipwhite(arg);
+ }
}
-theend:
if (silent_mode && did_show) {
// After displaying option values in silent mode.
silent_mode = false;
@@ -1516,15 +1582,15 @@ void did_set_option(int opt_idx, int opt_flags, int new_value, int value_checked
/// Convert a key name or string into a key value.
/// Used for 'wildchar' and 'cedit' options.
-int string_to_key(char_u *arg)
+int string_to_key(char *arg)
{
if (*arg == '<') {
- return find_key_option((char *)arg + 1, true);
+ return find_key_option(arg + 1, true);
}
if (*arg == '^') {
- return CTRL_CHR(arg[1]);
+ return CTRL_CHR((uint8_t)arg[1]);
}
- return *arg;
+ return (uint8_t)(*arg);
}
// When changing 'title', 'titlestring', 'icon' or 'iconstring', call
@@ -1597,9 +1663,9 @@ void set_options_bin(int oldval, int newval, int opt_flags)
/// number, return -1.
int get_shada_parameter(int type)
{
- char_u *p = find_shada_parameter(type);
+ char *p = find_shada_parameter(type);
if (p != NULL && ascii_isdigit(*p)) {
- return atoi((char *)p);
+ return atoi(p);
}
return -1;
}
@@ -1607,11 +1673,11 @@ int get_shada_parameter(int type)
/// Find the parameter represented by the given character (eg ''', ':', '"', or
/// '/') in the 'shada' option and return a pointer to the string after it.
/// Return NULL if the parameter is not specified in the string.
-char_u *find_shada_parameter(int type)
+char *find_shada_parameter(int type)
{
for (char *p = p_shada; *p; p++) {
if (*p == type) {
- return (char_u *)p + 1;
+ return p + 1;
}
if (*p == 'n') { // 'n' is always the last one
break;
@@ -1650,7 +1716,7 @@ static char *option_expand(int opt_idx, char *val)
// names.
// For 'spellsuggest' expand after "file:".
expand_env_esc(val, NameBuff, MAXPATHL,
- (char_u **)options[opt_idx].var == &p_tags, false,
+ (char **)options[opt_idx].var == &p_tags, false,
(char_u **)options[opt_idx].var == (char_u **)&p_sps ? "file:" :
NULL);
if (strcmp(NameBuff, val) == 0) { // they are the same
@@ -1703,9 +1769,7 @@ static void didset_options2(void)
/// Check for string options that are NULL (normally only termcap options).
void check_options(void)
{
- int opt_idx;
-
- for (opt_idx = 0; options[opt_idx].fullname != NULL; opt_idx++) {
+ for (int opt_idx = 0; options[opt_idx].fullname != NULL; opt_idx++) {
if ((options[opt_idx].flags & P_STRING) && options[opt_idx].var != NULL) {
check_string_option((char **)get_varp(&(options[opt_idx])));
}
@@ -1769,9 +1833,9 @@ void redraw_titles(void)
bool valid_name(const char *val, const char *allowed)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- for (const char_u *s = (char_u *)val; *s != NUL; s++) {
+ for (const char *s = val; *s != NUL; s++) {
if (!ASCII_ISALNUM(*s)
- && vim_strchr(allowed, *s) == NULL) {
+ && vim_strchr(allowed, (uint8_t)(*s)) == NULL) {
return false;
}
}
@@ -1970,7 +2034,7 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, const int va
|| (opt_flags & OPT_GLOBAL) || opt_flags == 0)
&& !bufIsChanged(bp) && bp->b_ml.ml_mfp != NULL) {
u_compute_hash(bp, hash);
- u_read_undo(NULL, hash, (char_u *)bp->b_fname);
+ u_read_undo(NULL, hash, bp->b_fname);
}
}
}
@@ -2256,8 +2320,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
errmsg = e_positive;
}
} else if (pp == &p_ch) {
- int minval = 0;
- if (value < minval) {
+ if (value < 0) {
errmsg = e_positive;
} else {
p_ch_was_zero = value == 0;
@@ -2593,7 +2656,7 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, char *errbuf,
}
/// Called after an option changed: check if something needs to be redrawn.
-void check_redraw(uint32_t flags)
+void check_redraw_for(buf_T *buf, win_T *win, uint32_t flags)
{
// Careful: P_RALL is a combination of other P_ flags
bool all = (flags & P_RALL) == P_RALL;
@@ -2607,19 +2670,24 @@ void check_redraw(uint32_t flags)
}
if ((flags & P_RBUF) || (flags & P_RWIN) || all) {
- changed_window_setting();
+ changed_window_setting_win(win);
}
if (flags & P_RBUF) {
- redraw_curbuf_later(UPD_NOT_VALID);
+ redraw_buf_later(buf, UPD_NOT_VALID);
}
if (flags & P_RWINONLY) {
- redraw_later(curwin, UPD_NOT_VALID);
+ redraw_later(win, UPD_NOT_VALID);
}
if (all) {
redraw_all_later(UPD_NOT_VALID);
}
}
+void check_redraw(uint32_t flags)
+{
+ check_redraw_for(curbuf, curwin, flags);
+}
+
/// Find index for named option
///
/// @param[in] arg Option to find index for.
@@ -2876,7 +2944,6 @@ int get_option_value_strict(char *name, int64_t *numval, char **stringval, int o
return SOPT_STRING | SOPT_GLOBAL;
}
- char_u *varp = NULL;
int rv = 0;
int opt_idx = findoption(name);
if (opt_idx < 0) {
@@ -2926,6 +2993,8 @@ int get_option_value_strict(char *name, int64_t *numval, char **stringval, int o
return rv;
}
+ char_u *varp = NULL;
+
if (opt_type == SREQ_GLOBAL) {
if (p->var == VAR_WIN) {
return 0;
@@ -3003,58 +3072,62 @@ char *set_option_value(const char *const name, const long number, const char *co
int opt_idx = findoption(name);
if (opt_idx < 0) {
semsg(_("E355: Unknown option: %s"), name);
- } else {
- uint32_t flags = options[opt_idx].flags;
- // Disallow changing some options in the sandbox
- if (sandbox > 0 && (flags & P_SECURE)) {
- emsg(_(e_sandbox));
- return NULL;
+ return NULL;
+ }
+
+ uint32_t flags = options[opt_idx].flags;
+ // Disallow changing some options in the sandbox
+ if (sandbox > 0 && (flags & P_SECURE)) {
+ emsg(_(e_sandbox));
+ return NULL;
+ }
+
+ if (flags & P_STRING) {
+ const char *s = string;
+ if (s == NULL || opt_flags & OPT_CLEAR) {
+ s = "";
}
- if (flags & P_STRING) {
- const char *s = string;
- if (s == NULL || opt_flags & OPT_CLEAR) {
- s = "";
- }
- return set_string_option(opt_idx, s, opt_flags);
- }
-
- char_u *varp = (char_u *)get_varp_scope(&(options[opt_idx]), opt_flags);
- if (varp != NULL) { // hidden option is not changed
- if (number == 0 && string != NULL) {
- int idx;
-
- // Either we are given a string or we are setting option
- // to zero.
- for (idx = 0; string[idx] == '0'; idx++) {}
- if (string[idx] != NUL || idx == 0) {
- // There's another character after zeros or the string
- // is empty. In both cases, we are trying to set a
- // num option using a string.
- semsg(_("E521: Number required: &%s = '%s'"),
- name, string);
- return NULL; // do nothing as we hit an error
- }
- }
- long numval = number;
- if (opt_flags & OPT_CLEAR) {
- if ((int *)varp == &curbuf->b_p_ar) {
- numval = -1;
- } else if ((long *)varp == &curbuf->b_p_ul) {
- numval = NO_LOCAL_UNDOLEVEL;
- } else if ((long *)varp == &curwin->w_p_so || (long *)varp == &curwin->w_p_siso) {
- numval = -1;
- } else {
- char *s = NULL;
- (void)get_option_value(name, &numval, &s, NULL, OPT_GLOBAL);
- }
- }
- if (flags & P_NUM) {
- return set_num_option(opt_idx, varp, numval, NULL, 0, opt_flags);
- }
- return set_bool_option(opt_idx, varp, (int)numval, opt_flags);
+ return set_string_option(opt_idx, s, opt_flags);
+ }
+
+ char_u *varp = (char_u *)get_varp_scope(&(options[opt_idx]), opt_flags);
+ if (varp == NULL) {
+ // hidden option is not changed
+ return NULL;
+ }
+
+ if (number == 0 && string != NULL) {
+ int idx;
+
+ // Either we are given a string or we are setting option
+ // to zero.
+ for (idx = 0; string[idx] == '0'; idx++) {}
+ if (string[idx] != NUL || idx == 0) {
+ // There's another character after zeros or the string
+ // is empty. In both cases, we are trying to set a
+ // num option using a string.
+ semsg(_("E521: Number required: &%s = '%s'"),
+ name, string);
+ return NULL; // do nothing as we hit an error
+ }
+ }
+ long numval = number;
+ if (opt_flags & OPT_CLEAR) {
+ if ((int *)varp == &curbuf->b_p_ar) {
+ numval = -1;
+ } else if ((long *)varp == &curbuf->b_p_ul) {
+ numval = NO_LOCAL_UNDOLEVEL;
+ } else if ((long *)varp == &curwin->w_p_so || (long *)varp == &curwin->w_p_siso) {
+ numval = -1;
+ } else {
+ char *s = NULL;
+ (void)get_option_value(name, &numval, &s, NULL, OPT_GLOBAL);
}
}
- return NULL;
+ if (flags & P_NUM) {
+ return set_num_option(opt_idx, varp, numval, NULL, 0, opt_flags);
+ }
+ return set_bool_option(opt_idx, varp, (int)numval, opt_flags);
}
/// Call set_option_value() and when an error is returned report it.
@@ -3086,10 +3159,10 @@ bool is_string_option(const char *name)
// Translate a string like "t_xx", "<t_xx>" or "<S-Tab>" to a key number.
// When "has_lt" is true there is a '<' before "*arg_arg".
// Returns 0 when the key is not recognized.
-int find_key_option_len(const char_u *arg_arg, size_t len, bool has_lt)
+int find_key_option_len(const char *arg_arg, size_t len, bool has_lt)
{
int key = 0;
- const char *arg = (char *)arg_arg;
+ const char *arg = arg_arg;
// Don't use get_special_key_code() for t_xx, we don't want it to call
// add_termcap_entry().
@@ -3109,14 +3182,14 @@ int find_key_option_len(const char_u *arg_arg, size_t len, bool has_lt)
static int find_key_option(const char *arg, bool has_lt)
{
- return find_key_option_len((char_u *)arg, strlen(arg), has_lt);
+ return find_key_option_len(arg, strlen(arg), has_lt);
}
-/// if 'all' == 0: show changed options
-/// if 'all' == 1: show all normal options
+/// if 'all' == false: show changed options
+/// if 'all' == true: show all normal options
///
/// @param opt_flags OPT_LOCAL and/or OPT_GLOBAL
-static void showoptions(int all, int opt_flags)
+static void showoptions(bool all, int opt_flags)
{
#define INC 20
#define GAP 3
@@ -3427,12 +3500,13 @@ int makefoldset(FILE *fd)
static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_t flags)
{
- char_u *buf = NULL;
- char_u *part = NULL;
-
if (fprintf(fd, "%s %s=", cmd, name) < 0) {
return FAIL;
}
+
+ char *buf = NULL;
+ char_u *part = NULL;
+
if (*valuep != NULL) {
// Output 'pastetoggle' as key names. For other
// options some characters have to be escaped with
@@ -3440,7 +3514,7 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_
if (valuep == &p_pt) {
char_u *s = (char_u *)(*valuep);
while (*s != NUL) {
- if (put_escstr(fd, (char_u *)str2special((const char **)&s, false, false), 2) == FAIL) {
+ if (put_escstr(fd, (char *)str2special((const char **)&s, false, false), 2) == FAIL) {
return FAIL;
}
}
@@ -3449,7 +3523,7 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_
// replace home directory in the whole option value into "buf"
buf = xmalloc(size);
- home_replace(NULL, *valuep, (char *)buf, size, false);
+ home_replace(NULL, *valuep, buf, size, false);
// If the option value is longer than MAXPATHL, we need to append
// each comma separated part of the option separately, so that it
@@ -3462,7 +3536,7 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_
if (put_eol(fd) == FAIL) {
goto fail;
}
- char *p = (char *)buf;
+ char *p = buf;
while (*p != NUL) {
// for each comma separated option part, append value to
// the option, :set rtp+=value
@@ -3470,7 +3544,7 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_
goto fail;
}
(void)copy_option_part(&p, (char *)part, size, ",");
- if (put_escstr(fd, part, 2) == FAIL || put_eol(fd) == FAIL) {
+ if (put_escstr(fd, (char *)part, 2) == FAIL || put_eol(fd) == FAIL) {
goto fail;
}
}
@@ -3483,7 +3557,7 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_
return FAIL;
}
xfree(buf);
- } else if (put_escstr(fd, (char_u *)(*valuep), 2) == FAIL) {
+ } else if (put_escstr(fd, *valuep, 2) == FAIL) {
return FAIL;
}
}
@@ -3499,11 +3573,10 @@ fail:
static int put_setnum(FILE *fd, char *cmd, char *name, long *valuep)
{
- long wc;
-
if (fprintf(fd, "%s %s=", cmd, name) < 0) {
return FAIL;
}
+ long wc;
if (wc_use_keyname((char_u *)valuep, &wc)) {
// print 'wildchar' and 'wildcharm' as a key name
if (fputs((char *)get_special_key_name((int)wc, 0), fd) < 0) {
@@ -3639,83 +3712,87 @@ void unset_global_local_option(char *name, void *from)
}
}
-/// Get pointer to option variable, depending on local or global scope.
-///
-/// @param scope can be OPT_LOCAL, OPT_GLOBAL or a combination.
-char *get_varp_scope(vimoption_T *p, int scope)
+char *get_varp_scope_from(vimoption_T *p, int scope, buf_T *buf, win_T *win)
{
if ((scope & OPT_GLOBAL) && p->indir != PV_NONE) {
if (p->var == VAR_WIN) {
- return GLOBAL_WO(get_varp(p));
+ return GLOBAL_WO(get_varp_from(p, buf, win));
}
return (char *)p->var;
}
if ((scope & OPT_LOCAL) && ((int)p->indir & PV_BOTH)) {
switch ((int)p->indir) {
case PV_FP:
- return (char *)&(curbuf->b_p_fp);
+ return (char *)&(buf->b_p_fp);
case PV_EFM:
- return (char *)&(curbuf->b_p_efm);
+ return (char *)&(buf->b_p_efm);
case PV_GP:
- return (char *)&(curbuf->b_p_gp);
+ return (char *)&(buf->b_p_gp);
case PV_MP:
- return (char *)&(curbuf->b_p_mp);
+ return (char *)&(buf->b_p_mp);
case PV_EP:
- return (char *)&(curbuf->b_p_ep);
+ return (char *)&(buf->b_p_ep);
case PV_KP:
- return (char *)&(curbuf->b_p_kp);
+ return (char *)&(buf->b_p_kp);
case PV_PATH:
- return (char *)&(curbuf->b_p_path);
+ return (char *)&(buf->b_p_path);
case PV_AR:
- return (char *)&(curbuf->b_p_ar);
+ return (char *)&(buf->b_p_ar);
case PV_TAGS:
- return (char *)&(curbuf->b_p_tags);
+ return (char *)&(buf->b_p_tags);
case PV_TC:
- return (char *)&(curbuf->b_p_tc);
+ return (char *)&(buf->b_p_tc);
case PV_SISO:
- return (char *)&(curwin->w_p_siso);
+ return (char *)&(win->w_p_siso);
case PV_SO:
- return (char *)&(curwin->w_p_so);
+ return (char *)&(win->w_p_so);
case PV_DEF:
- return (char *)&(curbuf->b_p_def);
+ return (char *)&(buf->b_p_def);
case PV_INC:
- return (char *)&(curbuf->b_p_inc);
+ return (char *)&(buf->b_p_inc);
case PV_DICT:
- return (char *)&(curbuf->b_p_dict);
+ return (char *)&(buf->b_p_dict);
case PV_TSR:
- return (char *)&(curbuf->b_p_tsr);
+ return (char *)&(buf->b_p_tsr);
case PV_TSRFU:
- return (char *)&(curbuf->b_p_tsrfu);
+ return (char *)&(buf->b_p_tsrfu);
case PV_TFU:
- return (char *)&(curbuf->b_p_tfu);
+ return (char *)&(buf->b_p_tfu);
case PV_SBR:
- return (char *)&(curwin->w_p_sbr);
+ return (char *)&(win->w_p_sbr);
case PV_STL:
- return (char *)&(curwin->w_p_stl);
+ return (char *)&(win->w_p_stl);
case PV_WBR:
- return (char *)&(curwin->w_p_wbr);
+ return (char *)&(win->w_p_wbr);
case PV_UL:
- return (char *)&(curbuf->b_p_ul);
+ return (char *)&(buf->b_p_ul);
case PV_LW:
- return (char *)&(curbuf->b_p_lw);
+ return (char *)&(buf->b_p_lw);
case PV_BKC:
- return (char *)&(curbuf->b_p_bkc);
+ return (char *)&(buf->b_p_bkc);
case PV_MENC:
- return (char *)&(curbuf->b_p_menc);
+ return (char *)&(buf->b_p_menc);
case PV_FCS:
- return (char *)&(curwin->w_p_fcs);
+ return (char *)&(win->w_p_fcs);
case PV_LCS:
- return (char *)&(curwin->w_p_lcs);
+ return (char *)&(win->w_p_lcs);
case PV_VE:
- return (char *)&(curwin->w_p_ve);
+ return (char *)&(win->w_p_ve);
}
return NULL; // "cannot happen"
}
- return (char *)get_varp(p);
+ return (char *)get_varp_from(p, buf, win);
}
-/// Get pointer to option variable.
-static char_u *get_varp(vimoption_T *p)
+/// Get pointer to option variable, depending on local or global scope.
+///
+/// @param scope can be OPT_LOCAL, OPT_GLOBAL or a combination.
+char *get_varp_scope(vimoption_T *p, int scope)
+{
+ return get_varp_scope_from(p, scope, curbuf, curwin);
+}
+
+static char_u *get_varp_from(vimoption_T *p, buf_T *buf, win_T *win)
{
// hidden option, always return NULL
if (p->var == NULL) {
@@ -3728,314 +3805,320 @@ static char_u *get_varp(vimoption_T *p)
// global option with local value: use local value if it's been set
case PV_EP:
- return *curbuf->b_p_ep != NUL
- ? (char_u *)&curbuf->b_p_ep : p->var;
+ return *buf->b_p_ep != NUL
+ ? (char_u *)&buf->b_p_ep : p->var;
case PV_KP:
- return *curbuf->b_p_kp != NUL
- ? (char_u *)&curbuf->b_p_kp : p->var;
+ return *buf->b_p_kp != NUL
+ ? (char_u *)&buf->b_p_kp : p->var;
case PV_PATH:
- return *curbuf->b_p_path != NUL
- ? (char_u *)&(curbuf->b_p_path) : p->var;
+ return *buf->b_p_path != NUL
+ ? (char_u *)&(buf->b_p_path) : p->var;
case PV_AR:
- return curbuf->b_p_ar >= 0
- ? (char_u *)&(curbuf->b_p_ar) : p->var;
+ return buf->b_p_ar >= 0
+ ? (char_u *)&(buf->b_p_ar) : p->var;
case PV_TAGS:
- return *curbuf->b_p_tags != NUL
- ? (char_u *)&(curbuf->b_p_tags) : p->var;
+ return *buf->b_p_tags != NUL
+ ? (char_u *)&(buf->b_p_tags) : p->var;
case PV_TC:
- return *curbuf->b_p_tc != NUL
- ? (char_u *)&(curbuf->b_p_tc) : p->var;
+ return *buf->b_p_tc != NUL
+ ? (char_u *)&(buf->b_p_tc) : p->var;
case PV_SISO:
- return curwin->w_p_siso >= 0
- ? (char_u *)&(curwin->w_p_siso) : p->var;
+ return win->w_p_siso >= 0
+ ? (char_u *)&(win->w_p_siso) : p->var;
case PV_SO:
- return curwin->w_p_so >= 0
- ? (char_u *)&(curwin->w_p_so) : p->var;
+ return win->w_p_so >= 0
+ ? (char_u *)&(win->w_p_so) : p->var;
case PV_BKC:
- return *curbuf->b_p_bkc != NUL
- ? (char_u *)&(curbuf->b_p_bkc) : p->var;
+ return *buf->b_p_bkc != NUL
+ ? (char_u *)&(buf->b_p_bkc) : p->var;
case PV_DEF:
- return *curbuf->b_p_def != NUL
- ? (char_u *)&(curbuf->b_p_def) : p->var;
+ return *buf->b_p_def != NUL
+ ? (char_u *)&(buf->b_p_def) : p->var;
case PV_INC:
- return *curbuf->b_p_inc != NUL
- ? (char_u *)&(curbuf->b_p_inc) : p->var;
+ return *buf->b_p_inc != NUL
+ ? (char_u *)&(buf->b_p_inc) : p->var;
case PV_DICT:
- return *curbuf->b_p_dict != NUL
- ? (char_u *)&(curbuf->b_p_dict) : p->var;
+ return *buf->b_p_dict != NUL
+ ? (char_u *)&(buf->b_p_dict) : p->var;
case PV_TSR:
- return *curbuf->b_p_tsr != NUL
- ? (char_u *)&(curbuf->b_p_tsr) : p->var;
+ return *buf->b_p_tsr != NUL
+ ? (char_u *)&(buf->b_p_tsr) : p->var;
case PV_TSRFU:
- return *curbuf->b_p_tsrfu != NUL
- ? (char_u *)&(curbuf->b_p_tsrfu) : p->var;
+ return *buf->b_p_tsrfu != NUL
+ ? (char_u *)&(buf->b_p_tsrfu) : p->var;
case PV_FP:
- return *curbuf->b_p_fp != NUL
- ? (char_u *)&(curbuf->b_p_fp) : p->var;
+ return *buf->b_p_fp != NUL
+ ? (char_u *)&(buf->b_p_fp) : p->var;
case PV_EFM:
- return *curbuf->b_p_efm != NUL
- ? (char_u *)&(curbuf->b_p_efm) : p->var;
+ return *buf->b_p_efm != NUL
+ ? (char_u *)&(buf->b_p_efm) : p->var;
case PV_GP:
- return *curbuf->b_p_gp != NUL
- ? (char_u *)&(curbuf->b_p_gp) : p->var;
+ return *buf->b_p_gp != NUL
+ ? (char_u *)&(buf->b_p_gp) : p->var;
case PV_MP:
- return *curbuf->b_p_mp != NUL
- ? (char_u *)&(curbuf->b_p_mp) : p->var;
+ return *buf->b_p_mp != NUL
+ ? (char_u *)&(buf->b_p_mp) : p->var;
case PV_SBR:
- return *curwin->w_p_sbr != NUL
- ? (char_u *)&(curwin->w_p_sbr) : p->var;
+ return *win->w_p_sbr != NUL
+ ? (char_u *)&(win->w_p_sbr) : p->var;
case PV_STL:
- return *curwin->w_p_stl != NUL
- ? (char_u *)&(curwin->w_p_stl) : p->var;
+ return *win->w_p_stl != NUL
+ ? (char_u *)&(win->w_p_stl) : p->var;
case PV_WBR:
- return *curwin->w_p_wbr != NUL
- ? (char_u *)&(curwin->w_p_wbr) : p->var;
+ return *win->w_p_wbr != NUL
+ ? (char_u *)&(win->w_p_wbr) : p->var;
case PV_UL:
- return curbuf->b_p_ul != NO_LOCAL_UNDOLEVEL
- ? (char_u *)&(curbuf->b_p_ul) : p->var;
+ return buf->b_p_ul != NO_LOCAL_UNDOLEVEL
+ ? (char_u *)&(buf->b_p_ul) : p->var;
case PV_LW:
- return *curbuf->b_p_lw != NUL
- ? (char_u *)&(curbuf->b_p_lw) : p->var;
+ return *buf->b_p_lw != NUL
+ ? (char_u *)&(buf->b_p_lw) : p->var;
case PV_MENC:
- return *curbuf->b_p_menc != NUL
- ? (char_u *)&(curbuf->b_p_menc) : p->var;
+ return *buf->b_p_menc != NUL
+ ? (char_u *)&(buf->b_p_menc) : p->var;
case PV_FCS:
- return *curwin->w_p_fcs != NUL
- ? (char_u *)&(curwin->w_p_fcs) : p->var;
+ return *win->w_p_fcs != NUL
+ ? (char_u *)&(win->w_p_fcs) : p->var;
case PV_LCS:
- return *curwin->w_p_lcs != NUL
- ? (char_u *)&(curwin->w_p_lcs) : p->var;
+ return *win->w_p_lcs != NUL
+ ? (char_u *)&(win->w_p_lcs) : p->var;
case PV_VE:
- return *curwin->w_p_ve != NUL
- ? (char_u *)&curwin->w_p_ve : p->var;
+ return *win->w_p_ve != NUL
+ ? (char_u *)&win->w_p_ve : p->var;
case PV_ARAB:
- return (char_u *)&(curwin->w_p_arab);
+ return (char_u *)&(win->w_p_arab);
case PV_LIST:
- return (char_u *)&(curwin->w_p_list);
+ return (char_u *)&(win->w_p_list);
case PV_SPELL:
- return (char_u *)&(curwin->w_p_spell);
+ return (char_u *)&(win->w_p_spell);
case PV_CUC:
- return (char_u *)&(curwin->w_p_cuc);
+ return (char_u *)&(win->w_p_cuc);
case PV_CUL:
- return (char_u *)&(curwin->w_p_cul);
+ return (char_u *)&(win->w_p_cul);
case PV_CULOPT:
- return (char_u *)&(curwin->w_p_culopt);
+ return (char_u *)&(win->w_p_culopt);
case PV_CC:
- return (char_u *)&(curwin->w_p_cc);
+ return (char_u *)&(win->w_p_cc);
case PV_DIFF:
- return (char_u *)&(curwin->w_p_diff);
+ return (char_u *)&(win->w_p_diff);
case PV_FDC:
- return (char_u *)&(curwin->w_p_fdc);
+ return (char_u *)&(win->w_p_fdc);
case PV_FEN:
- return (char_u *)&(curwin->w_p_fen);
+ return (char_u *)&(win->w_p_fen);
case PV_FDI:
- return (char_u *)&(curwin->w_p_fdi);
+ return (char_u *)&(win->w_p_fdi);
case PV_FDL:
- return (char_u *)&(curwin->w_p_fdl);
+ return (char_u *)&(win->w_p_fdl);
case PV_FDM:
- return (char_u *)&(curwin->w_p_fdm);
+ return (char_u *)&(win->w_p_fdm);
case PV_FML:
- return (char_u *)&(curwin->w_p_fml);
+ return (char_u *)&(win->w_p_fml);
case PV_FDN:
- return (char_u *)&(curwin->w_p_fdn);
+ return (char_u *)&(win->w_p_fdn);
case PV_FDE:
- return (char_u *)&(curwin->w_p_fde);
+ return (char_u *)&(win->w_p_fde);
case PV_FDT:
- return (char_u *)&(curwin->w_p_fdt);
+ return (char_u *)&(win->w_p_fdt);
case PV_FMR:
- return (char_u *)&(curwin->w_p_fmr);
+ return (char_u *)&(win->w_p_fmr);
case PV_NU:
- return (char_u *)&(curwin->w_p_nu);
+ return (char_u *)&(win->w_p_nu);
case PV_RNU:
- return (char_u *)&(curwin->w_p_rnu);
+ return (char_u *)&(win->w_p_rnu);
case PV_NUW:
- return (char_u *)&(curwin->w_p_nuw);
+ return (char_u *)&(win->w_p_nuw);
case PV_WFH:
- return (char_u *)&(curwin->w_p_wfh);
+ return (char_u *)&(win->w_p_wfh);
case PV_WFW:
- return (char_u *)&(curwin->w_p_wfw);
+ return (char_u *)&(win->w_p_wfw);
case PV_PVW:
- return (char_u *)&(curwin->w_p_pvw);
+ return (char_u *)&(win->w_p_pvw);
case PV_RL:
- return (char_u *)&(curwin->w_p_rl);
+ return (char_u *)&(win->w_p_rl);
case PV_RLC:
- return (char_u *)&(curwin->w_p_rlc);
+ return (char_u *)&(win->w_p_rlc);
case PV_SCROLL:
- return (char_u *)&(curwin->w_p_scr);
+ return (char_u *)&(win->w_p_scr);
case PV_WRAP:
- return (char_u *)&(curwin->w_p_wrap);
+ return (char_u *)&(win->w_p_wrap);
case PV_LBR:
- return (char_u *)&(curwin->w_p_lbr);
+ return (char_u *)&(win->w_p_lbr);
case PV_BRI:
- return (char_u *)&(curwin->w_p_bri);
+ return (char_u *)&(win->w_p_bri);
case PV_BRIOPT:
- return (char_u *)&(curwin->w_p_briopt);
+ return (char_u *)&(win->w_p_briopt);
case PV_SCBIND:
- return (char_u *)&(curwin->w_p_scb);
+ return (char_u *)&(win->w_p_scb);
case PV_CRBIND:
- return (char_u *)&(curwin->w_p_crb);
+ return (char_u *)&(win->w_p_crb);
case PV_COCU:
- return (char_u *)&(curwin->w_p_cocu);
+ return (char_u *)&(win->w_p_cocu);
case PV_COLE:
- return (char_u *)&(curwin->w_p_cole);
+ return (char_u *)&(win->w_p_cole);
case PV_AI:
- return (char_u *)&(curbuf->b_p_ai);
+ return (char_u *)&(buf->b_p_ai);
case PV_BIN:
- return (char_u *)&(curbuf->b_p_bin);
+ return (char_u *)&(buf->b_p_bin);
case PV_BOMB:
- return (char_u *)&(curbuf->b_p_bomb);
+ return (char_u *)&(buf->b_p_bomb);
case PV_BH:
- return (char_u *)&(curbuf->b_p_bh);
+ return (char_u *)&(buf->b_p_bh);
case PV_BT:
- return (char_u *)&(curbuf->b_p_bt);
+ return (char_u *)&(buf->b_p_bt);
case PV_BL:
- return (char_u *)&(curbuf->b_p_bl);
+ return (char_u *)&(buf->b_p_bl);
case PV_CHANNEL:
- return (char_u *)&(curbuf->b_p_channel);
+ return (char_u *)&(buf->b_p_channel);
case PV_CI:
- return (char_u *)&(curbuf->b_p_ci);
+ return (char_u *)&(buf->b_p_ci);
case PV_CIN:
- return (char_u *)&(curbuf->b_p_cin);
+ return (char_u *)&(buf->b_p_cin);
case PV_CINK:
- return (char_u *)&(curbuf->b_p_cink);
+ return (char_u *)&(buf->b_p_cink);
case PV_CINO:
- return (char_u *)&(curbuf->b_p_cino);
+ return (char_u *)&(buf->b_p_cino);
case PV_CINSD:
- return (char_u *)&(curbuf->b_p_cinsd);
+ return (char_u *)&(buf->b_p_cinsd);
case PV_CINW:
- return (char_u *)&(curbuf->b_p_cinw);
+ return (char_u *)&(buf->b_p_cinw);
case PV_COM:
- return (char_u *)&(curbuf->b_p_com);
+ return (char_u *)&(buf->b_p_com);
case PV_CMS:
- return (char_u *)&(curbuf->b_p_cms);
+ return (char_u *)&(buf->b_p_cms);
case PV_CPT:
- return (char_u *)&(curbuf->b_p_cpt);
+ return (char_u *)&(buf->b_p_cpt);
#ifdef BACKSLASH_IN_FILENAME
case PV_CSL:
- return (char_u *)&(curbuf->b_p_csl);
+ return (char_u *)&(buf->b_p_csl);
#endif
case PV_CFU:
- return (char_u *)&(curbuf->b_p_cfu);
+ return (char_u *)&(buf->b_p_cfu);
case PV_OFU:
- return (char_u *)&(curbuf->b_p_ofu);
+ return (char_u *)&(buf->b_p_ofu);
case PV_EOF:
- return (char_u *)&(curbuf->b_p_eof);
+ return (char_u *)&(buf->b_p_eof);
case PV_EOL:
- return (char_u *)&(curbuf->b_p_eol);
+ return (char_u *)&(buf->b_p_eol);
case PV_FIXEOL:
- return (char_u *)&(curbuf->b_p_fixeol);
+ return (char_u *)&(buf->b_p_fixeol);
case PV_ET:
- return (char_u *)&(curbuf->b_p_et);
+ return (char_u *)&(buf->b_p_et);
case PV_FENC:
- return (char_u *)&(curbuf->b_p_fenc);
+ return (char_u *)&(buf->b_p_fenc);
case PV_FF:
- return (char_u *)&(curbuf->b_p_ff);
+ return (char_u *)&(buf->b_p_ff);
case PV_FT:
- return (char_u *)&(curbuf->b_p_ft);
+ return (char_u *)&(buf->b_p_ft);
case PV_FO:
- return (char_u *)&(curbuf->b_p_fo);
+ return (char_u *)&(buf->b_p_fo);
case PV_FLP:
- return (char_u *)&(curbuf->b_p_flp);
+ return (char_u *)&(buf->b_p_flp);
case PV_IMI:
- return (char_u *)&(curbuf->b_p_iminsert);
+ return (char_u *)&(buf->b_p_iminsert);
case PV_IMS:
- return (char_u *)&(curbuf->b_p_imsearch);
+ return (char_u *)&(buf->b_p_imsearch);
case PV_INF:
- return (char_u *)&(curbuf->b_p_inf);
+ return (char_u *)&(buf->b_p_inf);
case PV_ISK:
- return (char_u *)&(curbuf->b_p_isk);
+ return (char_u *)&(buf->b_p_isk);
case PV_INEX:
- return (char_u *)&(curbuf->b_p_inex);
+ return (char_u *)&(buf->b_p_inex);
case PV_INDE:
- return (char_u *)&(curbuf->b_p_inde);
+ return (char_u *)&(buf->b_p_inde);
case PV_INDK:
- return (char_u *)&(curbuf->b_p_indk);
+ return (char_u *)&(buf->b_p_indk);
case PV_FEX:
- return (char_u *)&(curbuf->b_p_fex);
+ return (char_u *)&(buf->b_p_fex);
case PV_LISP:
- return (char_u *)&(curbuf->b_p_lisp);
+ return (char_u *)&(buf->b_p_lisp);
case PV_LOP:
- return (char_u *)&(curbuf->b_p_lop);
+ return (char_u *)&(buf->b_p_lop);
case PV_ML:
- return (char_u *)&(curbuf->b_p_ml);
+ return (char_u *)&(buf->b_p_ml);
case PV_MPS:
- return (char_u *)&(curbuf->b_p_mps);
+ return (char_u *)&(buf->b_p_mps);
case PV_MA:
- return (char_u *)&(curbuf->b_p_ma);
+ return (char_u *)&(buf->b_p_ma);
case PV_MOD:
- return (char_u *)&(curbuf->b_changed);
+ return (char_u *)&(buf->b_changed);
case PV_NF:
- return (char_u *)&(curbuf->b_p_nf);
+ return (char_u *)&(buf->b_p_nf);
case PV_PI:
- return (char_u *)&(curbuf->b_p_pi);
+ return (char_u *)&(buf->b_p_pi);
case PV_QE:
- return (char_u *)&(curbuf->b_p_qe);
+ return (char_u *)&(buf->b_p_qe);
case PV_RO:
- return (char_u *)&(curbuf->b_p_ro);
+ return (char_u *)&(buf->b_p_ro);
case PV_SCBK:
- return (char_u *)&(curbuf->b_p_scbk);
+ return (char_u *)&(buf->b_p_scbk);
case PV_SI:
- return (char_u *)&(curbuf->b_p_si);
+ return (char_u *)&(buf->b_p_si);
case PV_STS:
- return (char_u *)&(curbuf->b_p_sts);
+ return (char_u *)&(buf->b_p_sts);
case PV_SUA:
- return (char_u *)&(curbuf->b_p_sua);
+ return (char_u *)&(buf->b_p_sua);
case PV_SWF:
- return (char_u *)&(curbuf->b_p_swf);
+ return (char_u *)&(buf->b_p_swf);
case PV_SMC:
- return (char_u *)&(curbuf->b_p_smc);
+ return (char_u *)&(buf->b_p_smc);
case PV_SYN:
- return (char_u *)&(curbuf->b_p_syn);
+ return (char_u *)&(buf->b_p_syn);
case PV_SPC:
- return (char_u *)&(curwin->w_s->b_p_spc);
+ return (char_u *)&(win->w_s->b_p_spc);
case PV_SPF:
- return (char_u *)&(curwin->w_s->b_p_spf);
+ return (char_u *)&(win->w_s->b_p_spf);
case PV_SPL:
- return (char_u *)&(curwin->w_s->b_p_spl);
+ return (char_u *)&(win->w_s->b_p_spl);
case PV_SPO:
- return (char_u *)&(curwin->w_s->b_p_spo);
+ return (char_u *)&(win->w_s->b_p_spo);
case PV_SW:
- return (char_u *)&(curbuf->b_p_sw);
+ return (char_u *)&(buf->b_p_sw);
case PV_TFU:
- return (char_u *)&(curbuf->b_p_tfu);
+ return (char_u *)&(buf->b_p_tfu);
case PV_TS:
- return (char_u *)&(curbuf->b_p_ts);
+ return (char_u *)&(buf->b_p_ts);
case PV_TW:
- return (char_u *)&(curbuf->b_p_tw);
+ return (char_u *)&(buf->b_p_tw);
case PV_UDF:
- return (char_u *)&(curbuf->b_p_udf);
+ return (char_u *)&(buf->b_p_udf);
case PV_WM:
- return (char_u *)&(curbuf->b_p_wm);
+ return (char_u *)&(buf->b_p_wm);
case PV_VSTS:
- return (char_u *)&(curbuf->b_p_vsts);
+ return (char_u *)&(buf->b_p_vsts);
case PV_VTS:
- return (char_u *)&(curbuf->b_p_vts);
+ return (char_u *)&(buf->b_p_vts);
case PV_KMAP:
- return (char_u *)&(curbuf->b_p_keymap);
+ return (char_u *)&(buf->b_p_keymap);
case PV_SCL:
- return (char_u *)&(curwin->w_p_scl);
+ return (char_u *)&(win->w_p_scl);
case PV_WINHL:
- return (char_u *)&(curwin->w_p_winhl);
+ return (char_u *)&(win->w_p_winhl);
case PV_WINBL:
- return (char_u *)&(curwin->w_p_winbl);
+ return (char_u *)&(win->w_p_winbl);
case PV_STC:
- return (char_u *)&(curwin->w_p_stc);
+ return (char_u *)&(win->w_p_stc);
default:
iemsg(_("E356: get_varp ERROR"));
}
// always return a valid pointer to avoid a crash!
- return (char_u *)&(curbuf->b_p_wm);
+ return (char_u *)&(buf->b_p_wm);
+}
+
+/// Get pointer to option variable.
+static inline char_u *get_varp(vimoption_T *p)
+{
+ return get_varp_from(p, curbuf, curwin);
}
/// Get the value of 'equalprg', either the buffer-local one or the global one.
-char_u *get_equalprg(void)
+char *get_equalprg(void)
{
if (*curbuf->b_p_ep == NUL) {
return p_ep;
}
- return (char_u *)curbuf->b_p_ep;
+ return curbuf->b_p_ep;
}
/// Copy options from one window to another.
@@ -4221,7 +4304,7 @@ static void init_buf_opt_idx(void)
void buf_copy_options(buf_T *buf, int flags)
{
int should_copy = true;
- char_u *save_p_isk = NULL; // init for GCC
+ char *save_p_isk = NULL; // init for GCC
int did_isk = false;
// Skip this when the option defaults have not been set yet. Happens when
@@ -4254,7 +4337,7 @@ void buf_copy_options(buf_T *buf, int flags)
// (jumping back to a help file with CTRL-T or CTRL-O)
bool dont_do_help = ((flags & BCO_NOHELP) && buf->b_help) || buf->b_p_initialized;
if (dont_do_help) { // don't free b_p_isk
- save_p_isk = (char_u *)buf->b_p_isk;
+ save_p_isk = buf->b_p_isk;
buf->b_p_isk = NULL;
}
// Always free the allocated strings. If not already initialized,
@@ -4449,7 +4532,7 @@ void buf_copy_options(buf_T *buf, int flags)
// Don't touch these at all when BCO_NOHELP is used and going from
// or to a help buffer.
if (dont_do_help) {
- buf->b_p_isk = (char *)save_p_isk;
+ buf->b_p_isk = save_p_isk;
if (p_vts && p_vts != empty_option && !buf->b_p_vts_array) {
(void)tabstop_set(p_vts, &buf->b_p_vts_array);
} else {
@@ -4504,15 +4587,15 @@ void reset_modifiable(void)
}
/// Set the global value for 'iminsert' to the local value.
-void set_iminsert_global(void)
+void set_iminsert_global(buf_T *buf)
{
- p_iminsert = curbuf->b_p_iminsert;
+ p_iminsert = buf->b_p_iminsert;
}
/// Set the global value for 'imsearch' to the local value.
-void set_imsearch_global(void)
+void set_imsearch_global(buf_T *buf)
{
- p_imsearch = curbuf->b_p_imsearch;
+ p_imsearch = buf->b_p_imsearch;
}
static int expand_option_idx = -1;
@@ -4522,11 +4605,6 @@ static int expand_option_flags = 0;
/// @param opt_flags OPT_GLOBAL and/or OPT_LOCAL
void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
{
- uint32_t flags = 0; // init for GCC
- int opt_idx = 0; // init for GCC
- char *p;
- int is_term_option = false;
-
expand_option_flags = opt_flags;
xp->xp_context = EXPAND_SETTINGS;
@@ -4534,7 +4612,7 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
xp->xp_pattern = arg;
return;
}
- p = arg + strlen(arg) - 1;
+ char *p = arg + strlen(arg) - 1;
if (*p == ' ' && *(p - 1) != '\\') {
xp->xp_pattern = p + 1;
return;
@@ -4566,6 +4644,9 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
arg = p;
char nextchar;
+ uint32_t flags = 0;
+ int opt_idx = 0;
+ int is_term_option = false;
if (*arg == '<') {
while (*p != '>') {
@@ -4696,13 +4777,56 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
}
}
-int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char ***file)
+/// Returns true if "str" either matches "regmatch" or fuzzy matches "pat".
+///
+/// If "test_only" is true and "fuzzy" is false and if "str" matches the regular
+/// expression "regmatch", then returns true. Otherwise returns false.
+///
+/// If "test_only" is false and "fuzzy" is false and if "str" matches the
+/// regular expression "regmatch", then stores the match in matches[idx] and
+/// returns true.
+///
+/// If "test_only" is true and "fuzzy" is true and if "str" fuzzy matches
+/// "fuzzystr", then returns true. Otherwise returns false.
+///
+/// If "test_only" is false and "fuzzy" is true and if "str" fuzzy matches
+/// "fuzzystr", then stores the match details in fuzmatch[idx] and returns true.
+static bool match_str(char *const str, regmatch_T *const regmatch, char **const matches,
+ const int idx, const bool test_only, const bool fuzzy,
+ const char *const fuzzystr, fuzmatch_str_T *const fuzmatch)
+{
+ if (!fuzzy) {
+ if (vim_regexec(regmatch, str, (colnr_T)0)) {
+ if (!test_only) {
+ matches[idx] = xstrdup(str);
+ }
+ return true;
+ }
+ } else {
+ const int score = fuzzy_match_str(str, fuzzystr);
+ if (score != 0) {
+ if (!test_only) {
+ fuzmatch[idx].idx = idx;
+ fuzmatch[idx].str = xstrdup(str);
+ fuzmatch[idx].score = score;
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+int ExpandSettings(expand_T *xp, regmatch_T *regmatch, char *fuzzystr, int *numMatches,
+ char ***matches, const bool can_fuzzy)
{
int num_normal = 0; // Nr of matching non-term-code settings
int count = 0;
static char *(names[]) = { "all" };
int ic = regmatch->rm_ic; // remember the ignore-case flag
+ fuzmatch_str_T *fuzmatch = NULL;
+ const bool fuzzy = can_fuzzy && cmdline_fuzzy_complete(fuzzystr);
+
// do this loop twice:
// loop == 0: count the number of matching options
// loop == 1: copy the matching options into allocated memory
@@ -4712,11 +4836,12 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char ***fi
if (xp->xp_context != EXPAND_BOOL_SETTINGS) {
for (match = 0; match < (int)ARRAY_SIZE(names);
match++) {
- if (vim_regexec(regmatch, names[match], (colnr_T)0)) {
+ if (match_str(names[match], regmatch, *matches,
+ count, (loop == 0), fuzzy, fuzzystr, fuzmatch)) {
if (loop == 0) {
num_normal++;
} else {
- (*file)[count++] = xstrdup(names[match]);
+ count++;
}
}
}
@@ -4731,42 +4856,54 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char ***fi
&& !(options[opt_idx].flags & P_BOOL)) {
continue;
}
- match = false;
- if (vim_regexec(regmatch, str, (colnr_T)0)
- || (options[opt_idx].shortname != NULL
- && vim_regexec(regmatch,
- options[opt_idx].shortname,
- (colnr_T)0))) {
- match = true;
- }
- if (match) {
+ if (match_str(str, regmatch, *matches, count, (loop == 0),
+ fuzzy, fuzzystr, fuzmatch)) {
+ if (loop == 0) {
+ num_normal++;
+ } else {
+ count++;
+ }
+ } else if (!fuzzy && options[opt_idx].shortname != NULL
+ && vim_regexec(regmatch, options[opt_idx].shortname, (colnr_T)0)) {
+ // Compare against the abbreviated option name (for regular
+ // expression match). Fuzzy matching (previous if) already
+ // matches against both the expanded and abbreviated names.
if (loop == 0) {
num_normal++;
} else {
- (*file)[count++] = xstrdup(str);
+ (*matches)[count++] = xstrdup(str);
}
}
}
if (loop == 0) {
if (num_normal > 0) {
- *num_file = num_normal;
+ *numMatches = num_normal;
} else {
return OK;
}
- *file = xmalloc((size_t)(*num_file) * sizeof(char *));
+ if (!fuzzy) {
+ *matches = xmalloc((size_t)(*numMatches) * sizeof(char *));
+ } else {
+ fuzmatch = xmalloc((size_t)(*numMatches) * sizeof(fuzmatch_str_T));
+ }
}
}
+
+ if (fuzzy) {
+ fuzzymatches_to_strmatches(fuzmatch, matches, count, false);
+ }
+
return OK;
}
-void ExpandOldSetting(int *num_file, char ***file)
+void ExpandOldSetting(int *numMatches, char ***matches)
{
char *var = NULL;
- *num_file = 0;
- *file = xmalloc(sizeof(char_u *));
+ *numMatches = 0;
+ *matches = xmalloc(sizeof(char *));
// For a terminal key code expand_option_idx is < 0.
if (expand_option_idx < 0) {
@@ -4783,7 +4920,7 @@ void ExpandOldSetting(int *num_file, char ***file)
// A backslash is required before some characters. This is the reverse of
// what happens in do_set().
- char_u *buf = (char_u *)vim_strsave_escaped(var, (char *)escape_chars);
+ char *buf = vim_strsave_escaped(var, escape_chars);
#ifdef BACKSLASH_IN_FILENAME
// For MS-Windows et al. we don't double backslashes at the start and
@@ -4799,8 +4936,8 @@ void ExpandOldSetting(int *num_file, char ***file)
}
#endif
- *file[0] = (char *)buf;
- *num_file = 1;
+ *matches[0] = buf;
+ *numMatches = 1;
}
/// Get the value for the numeric or string option///opp in a nice format into
@@ -4817,7 +4954,7 @@ static void option_value2string(vimoption_T *opp, int scope)
if (wc_use_keyname((char_u *)varp, &wc)) {
xstrlcpy(NameBuff, (char *)get_special_key_name((int)wc, 0), sizeof(NameBuff));
} else if (wc != 0) {
- xstrlcpy(NameBuff, (char *)transchar((int)wc), sizeof(NameBuff));
+ xstrlcpy(NameBuff, transchar((int)wc), sizeof(NameBuff));
} else {
snprintf(NameBuff,
sizeof(NameBuff),
@@ -5035,10 +5172,11 @@ bool option_was_set(const char *name)
void reset_option_was_set(const char *name)
{
const int idx = findoption(name);
-
- if (idx >= 0) {
- options[idx].flags &= ~P_WAS_SET;
+ if (idx < 0) {
+ return;
}
+
+ options[idx].flags &= ~P_WAS_SET;
}
/// fill_breakat_flags() -- called when 'breakat' changes value.
@@ -5199,16 +5337,16 @@ unsigned int get_ve_flags(void)
///
/// @param win If not NULL, the window to get the local option from; global
/// otherwise.
-char_u *get_showbreak_value(win_T *const win)
+char *get_showbreak_value(win_T *const win)
FUNC_ATTR_WARN_UNUSED_RESULT
{
if (win->w_p_sbr == NULL || *win->w_p_sbr == NUL) {
- return (char_u *)p_sbr;
+ return p_sbr;
}
if (strcmp(win->w_p_sbr, "NONE") == 0) {
- return (char_u *)empty_option;
+ return empty_option;
}
- return (char_u *)win->w_p_sbr;
+ return win->w_p_sbr;
}
/// Return the current end-of-line type: EOL_DOS, EOL_UNIX or EOL_MAC.
@@ -5327,9 +5465,9 @@ size_t copy_option_part(char **option, char *buf, size_t maxlen, char *sep_chars
if (*p == '.') {
buf[len++] = *p++;
}
- while (*p != NUL && vim_strchr(sep_chars, *p) == NULL) {
+ while (*p != NUL && vim_strchr(sep_chars, (uint8_t)(*p)) == NULL) {
// Skip backslash before a separator character and space.
- if (p[0] == '\\' && vim_strchr(sep_chars, p[1]) != NULL) {
+ if (p[0] == '\\' && vim_strchr(sep_chars, (uint8_t)p[1]) != NULL) {
p++;
}
if (len < maxlen - 1) {
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index 3ffab71f22..d190fc5999 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -442,7 +442,7 @@ EXTERN unsigned bo_flags;
#define BO_SPELL 0x20000
#define BO_WILD 0x40000
-EXTERN char_u *p_bsk; // 'backupskip'
+EXTERN char *p_bsk; // 'backupskip'
EXTERN char *p_breakat; // 'breakat'
EXTERN char *p_bh; ///< 'bufhidden'
EXTERN char *p_bt; ///< 'buftype'
@@ -468,7 +468,7 @@ EXTERN long p_columns; // 'columns'
EXTERN int p_confirm; // 'confirm'
EXTERN char *p_cot; // 'completeopt'
#ifdef BACKSLASH_IN_FILENAME
-EXTERN char_u *p_csl; // 'completeslash'
+EXTERN char *p_csl; // 'completeslash'
#endif
EXTERN long p_pb; // 'pumblend'
EXTERN long p_ph; // 'pumheight'
@@ -494,9 +494,9 @@ EXTERN int p_ed; // 'edcompatible'
EXTERN char *p_ead; // 'eadirection'
EXTERN int p_emoji; // 'emoji'
EXTERN int p_ea; // 'equalalways'
-EXTERN char_u *p_ep; // 'equalprg'
+EXTERN char *p_ep; // 'equalprg'
EXTERN int p_eb; // 'errorbells'
-EXTERN char_u *p_ef; // 'errorfile'
+EXTERN char *p_ef; // 'errorfile'
EXTERN char *p_efm; // 'errorformat'
EXTERN char *p_gefm; // 'grepformat'
EXTERN char *p_gp; // 'grepprg'
@@ -531,12 +531,12 @@ EXTERN unsigned fdo_flags;
EXTERN char *p_fex; ///< 'formatexpr'
EXTERN char *p_flp; ///< 'formatlistpat'
EXTERN char *p_fo; ///< 'formatoptions'
-EXTERN char_u *p_fp; // 'formatprg'
+EXTERN char *p_fp; // 'formatprg'
EXTERN int p_fs; // 'fsync'
EXTERN int p_gd; // 'gdefault'
EXTERN char *p_guicursor; // 'guicursor'
-EXTERN char_u *p_guifont; // 'guifont'
-EXTERN char_u *p_guifontwide; // 'guifontwide'
+EXTERN char *p_guifont; // 'guifont'
+EXTERN char *p_guifontwide; // 'guifontwide'
EXTERN char *p_hf; // 'helpfile'
EXTERN long p_hh; // 'helpheight'
EXTERN char *p_hlg; // 'helplang'
@@ -568,17 +568,17 @@ EXTERN unsigned jop_flags;
#define JOP_STACK 0x01
#define JOP_VIEW 0x02
EXTERN char *p_keymap; ///< 'keymap'
-EXTERN char_u *p_kp; // 'keywordprg'
+EXTERN char *p_kp; // 'keywordprg'
EXTERN char *p_km; // 'keymodel'
EXTERN char *p_langmap; // 'langmap'
EXTERN int p_lnr; // 'langnoremap'
EXTERN int p_lrm; // 'langremap'
-EXTERN char_u *p_lm; // 'langmenu'
+EXTERN char *p_lm; // 'langmenu'
EXTERN long p_lines; // 'lines'
EXTERN long p_linespace; // 'linespace'
EXTERN int p_lisp; ///< 'lisp'
EXTERN char *p_lop; ///< 'lispoptions'
-EXTERN char_u *p_lispwords; // 'lispwords'
+EXTERN char *p_lispwords; // 'lispwords'
EXTERN long p_ls; // 'laststatus'
EXTERN long p_stal; // 'showtabline'
EXTERN char *p_lcs; // 'listchars'
@@ -588,7 +588,7 @@ EXTERN int p_lpl; // 'loadplugins'
EXTERN int p_magic; // 'magic'
EXTERN char *p_menc; // 'makeencoding'
EXTERN char *p_mef; // 'makeef'
-EXTERN char_u *p_mp; // 'makeprg'
+EXTERN char *p_mp; // 'makeprg'
EXTERN char *p_mps; ///< 'matchpairs'
EXTERN long p_mat; // 'matchtime'
EXTERN long p_mco; // 'maxcombine'
@@ -613,13 +613,13 @@ EXTERN long p_mouset; // 'mousetime'
EXTERN int p_more; // 'more'
EXTERN char *p_nf; ///< 'nrformats'
EXTERN char *p_opfunc; // 'operatorfunc'
-EXTERN char_u *p_para; // 'paragraphs'
+EXTERN char *p_para; // 'paragraphs'
EXTERN int p_paste; // 'paste'
EXTERN char *p_pt; // 'pastetoggle'
EXTERN char *p_pex; // 'patchexpr'
EXTERN char *p_pm; // 'patchmode'
-EXTERN char_u *p_path; // 'path'
-EXTERN char_u *p_cdpath; // 'cdpath'
+EXTERN char *p_path; // 'path'
+EXTERN char *p_cdpath; // 'cdpath'
EXTERN int p_pi; ///< 'preserveindent'
EXTERN long p_pyx; // 'pyxversion'
EXTERN char *p_qe; ///< 'quoteescape'
@@ -673,11 +673,11 @@ EXTERN unsigned ssop_flags;
#define SSOP_SKIP_RTP 0x20000
EXTERN char *p_sh; // 'shell'
-EXTERN char_u *p_shcf; // 'shellcmdflag'
+EXTERN char *p_shcf; // 'shellcmdflag'
EXTERN char *p_sp; // 'shellpipe'
EXTERN char *p_shq; // 'shellquote'
EXTERN char *p_sxq; // 'shellxquote'
-EXTERN char_u *p_sxe; // 'shellxescape'
+EXTERN char *p_sxe; // 'shellxescape'
EXTERN char *p_srr; // 'shellredir'
EXTERN int p_stmp; // 'shelltemp'
#ifdef BACKSLASH_IN_FILENAME
@@ -725,7 +725,7 @@ EXTERN unsigned int spo_flags;
EXTERN char *p_sps; // 'spellsuggest'
EXTERN int p_spr; // 'splitright'
EXTERN int p_sol; // 'startofline'
-EXTERN char_u *p_su; // 'suffixes'
+EXTERN char *p_su; // 'suffixes'
EXTERN char *p_swb; // 'switchbuf'
EXTERN unsigned swb_flags;
// Keep in sync with p_swb_values in optionstr.c
@@ -747,7 +747,7 @@ EXTERN unsigned tc_flags; ///< flags from 'tagcase'
#define TC_SMART 0x10
EXTERN long p_tl; ///< 'taglength'
EXTERN int p_tr; ///< 'tagrelative'
-EXTERN char_u *p_tags; ///< 'tags'
+EXTERN char *p_tags; ///< 'tags'
EXTERN int p_tgst; ///< 'tagstack'
EXTERN int p_tbidi; ///< 'termbidi'
EXTERN long p_tw; ///< 'textwidth'
@@ -756,13 +756,13 @@ EXTERN int p_timeout; ///< 'timeout'
EXTERN long p_tm; ///< 'timeoutlen'
EXTERN int p_title; ///< 'title'
EXTERN long p_titlelen; ///< 'titlelen'
-EXTERN char_u *p_titleold; ///< 'titleold'
+EXTERN char *p_titleold; ///< 'titleold'
EXTERN char *p_titlestring; ///< 'titlestring'
-EXTERN char_u *p_tsr; ///< 'thesaurus'
+EXTERN char *p_tsr; ///< 'thesaurus'
EXTERN int p_tgc; ///< 'termguicolors'
EXTERN int p_ttimeout; ///< 'ttimeout'
EXTERN long p_ttm; ///< 'ttimeoutlen'
-EXTERN char_u *p_udir; ///< 'undodir'
+EXTERN char *p_udir; ///< 'undodir'
EXTERN int p_udf; ///< 'undofile'
EXTERN long p_ul; ///< 'undolevels'
EXTERN long p_ur; ///< 'undoreload'
@@ -778,15 +778,15 @@ EXTERN unsigned vop_flags; ///< uses SSOP_ flags
EXTERN int p_vb; ///< 'visualbell'
EXTERN char *p_ve; ///< 'virtualedit'
EXTERN unsigned ve_flags;
-#define VE_BLOCK 5U // includes "all"
-#define VE_INSERT 6U // includes "all"
+#define VE_BLOCK 5U // includes "all"
+#define VE_INSERT 6U // includes "all"
#define VE_ALL 4U
#define VE_ONEMORE 8U
-#define VE_NONE 16U // "none"
-#define VE_NONEU 32U // "NONE"
+#define VE_NONE 16U // "none"
+#define VE_NONEU 32U // "NONE"
EXTERN long p_verbose; // 'verbose'
#ifdef IN_OPTION_C
-char_u *p_vfile = (char_u *)""; // used before options are initialized
+char *p_vfile = ""; // used before options are initialized
#else
extern char *p_vfile; // 'verbosefile'
#endif
@@ -795,6 +795,7 @@ EXTERN char *p_wop; // 'wildoptions'
EXTERN unsigned wop_flags;
#define WOP_TAGFILE 0x01
#define WOP_PUM 0x02
+#define WOP_FUZZY 0x04
EXTERN long p_window; // 'window'
EXTERN char *p_wak; // 'winaltkeys'
EXTERN char *p_wig; // 'wildignore'
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c
index a97e9b7c7e..ca50c3ab00 100644
--- a/src/nvim/optionstr.c
+++ b/src/nvim/optionstr.c
@@ -3,6 +3,7 @@
#include <assert.h>
#include <stdbool.h>
+#include <stdint.h>
#include <string.h>
#include "nvim/api/private/helpers.h"
@@ -90,7 +91,7 @@ static char *(p_swb_values[]) = { "useopen", "usetab", "split", "newtab", "vspli
static char *(p_spk_values[]) = { "cursor", "screen", "topline", NULL };
static char *(p_tc_values[]) = { "followic", "ignore", "match", "followscs", "smart", NULL };
static char *(p_ve_values[]) = { "block", "insert", "all", "onemore", "none", "NONE", NULL };
-static char *(p_wop_values[]) = { "tagfile", "pum", NULL };
+static char *(p_wop_values[]) = { "tagfile", "pum", "fuzzy", NULL };
static char *(p_wak_values[]) = { "yes", "menu", "no", NULL };
static char *(p_mousem_values[]) = { "extend", "popup", "popup_setpos", "mac", NULL };
static char *(p_sel_values[]) = { "inclusive", "exclusive", "old", NULL };
@@ -166,36 +167,37 @@ void trigger_optionset_string(int opt_idx, int opt_flags, char *oldval, char *ol
char *oldval_g, char *newval)
{
// Don't do this recursively.
- if (oldval != NULL
- && newval != NULL
- && *get_vim_var_str(VV_OPTION_TYPE) == NUL) {
- char buf_type[7];
+ if (oldval == NULL || newval == NULL
+ || *get_vim_var_str(VV_OPTION_TYPE) != NUL) {
+ return;
+ }
- vim_snprintf(buf_type, ARRAY_SIZE(buf_type), "%s",
- (opt_flags & OPT_LOCAL) ? "local" : "global");
- set_vim_var_string(VV_OPTION_OLD, oldval, -1);
- set_vim_var_string(VV_OPTION_NEW, newval, -1);
- set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
- if (opt_flags & OPT_LOCAL) {
- set_vim_var_string(VV_OPTION_COMMAND, "setlocal", -1);
- set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
- }
- if (opt_flags & OPT_GLOBAL) {
- set_vim_var_string(VV_OPTION_COMMAND, "setglobal", -1);
- set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval, -1);
- }
- if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) {
- set_vim_var_string(VV_OPTION_COMMAND, "set", -1);
- set_vim_var_string(VV_OPTION_OLDLOCAL, oldval_l, -1);
- set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval_g, -1);
- }
- if (opt_flags & OPT_MODELINE) {
- set_vim_var_string(VV_OPTION_COMMAND, "modeline", -1);
- set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
- }
- apply_autocmds(EVENT_OPTIONSET, get_option(opt_idx)->fullname, NULL, false, NULL);
- reset_v_option_vars();
+ char buf_type[7];
+
+ vim_snprintf(buf_type, ARRAY_SIZE(buf_type), "%s",
+ (opt_flags & OPT_LOCAL) ? "local" : "global");
+ set_vim_var_string(VV_OPTION_OLD, oldval, -1);
+ set_vim_var_string(VV_OPTION_NEW, newval, -1);
+ set_vim_var_string(VV_OPTION_TYPE, buf_type, -1);
+ if (opt_flags & OPT_LOCAL) {
+ set_vim_var_string(VV_OPTION_COMMAND, "setlocal", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
+ }
+ if (opt_flags & OPT_GLOBAL) {
+ set_vim_var_string(VV_OPTION_COMMAND, "setglobal", -1);
+ set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval, -1);
+ }
+ if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0) {
+ set_vim_var_string(VV_OPTION_COMMAND, "set", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, oldval_l, -1);
+ set_vim_var_string(VV_OPTION_OLDGLOBAL, oldval_g, -1);
+ }
+ if (opt_flags & OPT_MODELINE) {
+ set_vim_var_string(VV_OPTION_COMMAND, "modeline", -1);
+ set_vim_var_string(VV_OPTION_OLDLOCAL, oldval, -1);
}
+ apply_autocmds(EVENT_OPTIONSET, get_option(opt_idx)->fullname, NULL, false, NULL);
+ reset_v_option_vars();
}
static char *illegal_char(char *errbuf, size_t errbuflen, int c)
@@ -204,7 +206,7 @@ static char *illegal_char(char *errbuf, size_t errbuflen, int c)
return "";
}
vim_snprintf(errbuf, errbuflen, _("E539: Illegal character <%s>"),
- (char *)transchar(c));
+ transchar(c));
return errbuf;
}
@@ -612,8 +614,8 @@ char *check_stl_option(char *s)
groupdepth++;
continue;
}
- if (vim_strchr(STL_ALL, *s) == NULL) {
- return illegal_char(errbuf, sizeof(errbuf), *s);
+ if (vim_strchr(STL_ALL, (uint8_t)(*s)) == NULL) {
+ return illegal_char(errbuf, sizeof(errbuf), (uint8_t)(*s));
}
if (*s == '{') {
bool reevaluate = (*++s == '%');
@@ -636,952 +638,1238 @@ char *check_stl_option(char *s)
return NULL;
}
-static int shada_idx = -1;
+/// Check for a "normal" directory or file name in some options. Disallow a
+/// path separator (slash and/or backslash), wildcards and characters that are
+/// often illegal in a file name. Be more permissive if "secure" is off.
+static bool check_illegal_path_names(char *val, uint32_t flags)
+{
+ return (((flags & P_NFNAME)
+ && strpbrk(val, (secure ? "/\\*?[|;&<>\r\n" : "/\\*?[<>\r\n")) != NULL)
+ || ((flags & P_NDNAME)
+ && strpbrk(val, "*?[|;&<>\r\n") != NULL));
+}
-/// Handle string options that need some action to perform when changed.
-/// The new value must be allocated.
-///
-/// @param opt_idx index in options[] table
-/// @param varp pointer to the option variable
-/// @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
-///
-/// @return NULL for success, or an untranslated error message for an error
-char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf, size_t errbuflen,
- int opt_flags, int *value_checked)
+static void did_set_backupcopy(buf_T *buf, char *oldval, int opt_flags, char **errmsg)
{
- char *errmsg = NULL;
- char *s, *p;
- int did_chartab = false;
- vimoption_T *opt = get_option(opt_idx);
- bool free_oldval = (opt->flags & P_ALLOCED);
- bool value_changed = false;
+ char *bkc = p_bkc;
+ unsigned int *flags = &bkc_flags;
- // Get the global option to compare with, otherwise we would have to check
- // two values for all local options.
- char **gvarp = (char **)get_varp_scope(opt, OPT_GLOBAL);
+ if (opt_flags & OPT_LOCAL) {
+ bkc = buf->b_p_bkc;
+ flags = &buf->b_bkc_flags;
+ }
- // Disallow changing some options from secure mode
- if ((secure || sandbox != 0)
- && (opt->flags & P_SECURE)) {
- errmsg = e_secure;
- } else if (((opt->flags & P_NFNAME)
- && strpbrk(*varp, (secure ? "/\\*?[|;&<>\r\n" : "/\\*?[<>\r\n")) != NULL)
- || ((opt->flags & P_NDNAME)
- && strpbrk(*varp, "*?[|;&<>\r\n") != NULL)) {
- // Check for a "normal" directory or file name in some options. Disallow a
- // path separator (slash and/or backslash), wildcards and characters that
- // are often illegal in a file name. Be more permissive if "secure" is off.
- errmsg = e_invarg;
- } else if (gvarp == &p_bkc) { // 'backupcopy'
- char *bkc = p_bkc;
- unsigned int *flags = &bkc_flags;
+ if ((opt_flags & OPT_LOCAL) && *bkc == NUL) {
+ // make the local value empty: use the global value
+ *flags = 0;
+ } else {
+ if (opt_strings_flags(bkc, p_bkc_values, flags, true) != OK) {
+ *errmsg = e_invarg;
+ }
- if (opt_flags & OPT_LOCAL) {
- bkc = curbuf->b_p_bkc;
- flags = &curbuf->b_bkc_flags;
+ if (((*flags & BKC_AUTO) != 0)
+ + ((*flags & BKC_YES) != 0)
+ + ((*flags & BKC_NO) != 0) != 1) {
+ // Must have exactly one of "auto", "yes" and "no".
+ (void)opt_strings_flags(oldval, p_bkc_values, flags, true);
+ *errmsg = e_invarg;
}
+ }
+}
- if ((opt_flags & OPT_LOCAL) && *bkc == NUL) {
- // make the local value empty: use the global value
- *flags = 0;
- } else {
- if (opt_strings_flags(bkc, p_bkc_values, flags, true) != OK) {
- errmsg = e_invarg;
- }
+static void did_set_backupext_or_patchmode(char **errmsg)
+{
+ if (strcmp(*p_bex == '.' ? p_bex + 1 : p_bex,
+ *p_pm == '.' ? p_pm + 1 : p_pm) == 0) {
+ *errmsg = e_backupext_and_patchmode_are_equal;
+ }
+}
- if (((*flags & BKC_AUTO) != 0)
- + ((*flags & BKC_YES) != 0)
- + ((*flags & BKC_NO) != 0) != 1) {
- // Must have exactly one of "auto", "yes" and "no".
- (void)opt_strings_flags(oldval, p_bkc_values, flags, true);
- errmsg = e_invarg;
- }
- }
- } else if (varp == &p_bex || varp == &p_pm) { // 'backupext' and 'patchmode'
- if (strcmp(*p_bex == '.' ? p_bex + 1 : p_bex,
- *p_pm == '.' ? p_pm + 1 : p_pm) == 0) {
- errmsg = e_backupext_and_patchmode_are_equal;
- }
- } else if (varp == &curwin->w_p_briopt) { // 'breakindentopt'
- if (briopt_check(curwin) == FAIL) {
- errmsg = e_invarg;
- }
- // list setting requires a redraw
- if (curwin->w_briopt_list) {
- redraw_all_later(UPD_NOT_VALID);
- }
- } else if (varp == &p_isi
- || varp == &(curbuf->b_p_isk)
- || varp == &p_isp
- || varp == &p_isf) {
- // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill g_chartab[]
- // If the new option is invalid, use old value. 'lisp' option: refill
- // g_chartab[] for '-' char
- if (init_chartab() == FAIL) {
- did_chartab = true; // need to restore it below
- errmsg = e_invarg; // error in value
- }
- } else if (varp == &p_hf) { // 'helpfile'
- // May compute new values for $VIM and $VIMRUNTIME
- if (didset_vim) {
- vim_unsetenv_ext("VIM");
- }
- if (didset_vimruntime) {
- vim_unsetenv_ext("VIMRUNTIME");
- }
- } else if (varp == &p_rtp || varp == &p_pp) { // 'runtimepath' 'packpath'
- runtime_search_path_invalidate();
- } else if (varp == &curwin->w_p_culopt
- || gvarp == &curwin->w_allbuf_opt.wo_culopt) { // 'cursorlineopt'
- if (**varp == NUL || fill_culopt_flags(*varp, curwin) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &curwin->w_p_cc) { // 'colorcolumn'
- errmsg = check_colorcolumn(curwin);
- } else if (varp == &p_hlg) { // 'helplang'
- // Check for "", "ab", "ab,cd", etc.
- for (s = p_hlg; *s != NUL; s += 3) {
- if (s[1] == NUL || ((s[2] != ',' || s[3] == NUL) && s[2] != NUL)) {
- errmsg = e_invarg;
- break;
- }
- if (s[2] == NUL) {
- break;
- }
- }
- } else if (varp == &p_hl) { // 'highlight'
- if (strcmp(*varp, HIGHLIGHT_INIT) != 0) {
- errmsg = e_unsupportedoption;
- }
- } else if (varp == &p_jop) { // 'jumpoptions'
- if (opt_strings_flags(p_jop, p_jop_values, &jop_flags, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (gvarp == &p_nf) { // 'nrformats'
- if (check_opt_strings(*varp, p_nf_values, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_ssop) { // 'sessionoptions'
- if (opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, true) != OK) {
- errmsg = e_invarg;
- }
- if ((ssop_flags & SSOP_CURDIR) && (ssop_flags & SSOP_SESDIR)) {
- // Don't allow both "sesdir" and "curdir".
- (void)opt_strings_flags(oldval, p_ssop_values, &ssop_flags, true);
- errmsg = e_invarg;
- }
- } else if (varp == &p_vop) { // 'viewoptions'
- if (opt_strings_flags(p_vop, p_ssop_values, &vop_flags, true) != OK) {
- errmsg = e_invarg;
+static void did_set_breakindentopt(win_T *win, char **errmsg)
+{
+ if (briopt_check(win) == FAIL) {
+ *errmsg = e_invarg;
+ }
+ // list setting requires a redraw
+ if (win == curwin && win->w_briopt_list) {
+ redraw_all_later(UPD_NOT_VALID);
+ }
+}
+
+static void did_set_isopt(buf_T *buf, bool *did_chartab, char **errmsg)
+{
+ // 'isident', 'iskeyword', 'isprint or 'isfname' option: refill g_chartab[]
+ // If the new option is invalid, use old value.
+ // 'lisp' option: refill g_chartab[] for '-' char
+ if (buf_init_chartab(buf, true) == FAIL) {
+ *did_chartab = true; // need to restore it below
+ *errmsg = e_invarg; // error in value
+ }
+}
+
+static void did_set_helpfile(void)
+{
+ // May compute new values for $VIM and $VIMRUNTIME
+ if (didset_vim) {
+ vim_unsetenv_ext("VIM");
+ }
+ if (didset_vimruntime) {
+ vim_unsetenv_ext("VIMRUNTIME");
+ }
+}
+
+static void did_set_cursorlineopt(win_T *win, char **varp, char **errmsg)
+{
+ if (**varp == NUL || fill_culopt_flags(*varp, win) != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_helplang(char **errmsg)
+{
+ // Check for "", "ab", "ab,cd", etc.
+ for (char *s = p_hlg; *s != NUL; s += 3) {
+ if (s[1] == NUL || ((s[2] != ',' || s[3] == NUL) && s[2] != NUL)) {
+ *errmsg = e_invarg;
+ break;
}
- } else if (varp == &p_rdb) { // 'redrawdebug'
- if (opt_strings_flags(p_rdb, p_rdb_values, &rdb_flags, true) != OK) {
- errmsg = e_invarg;
+ if (s[2] == NUL) {
+ break;
}
- } else if (varp == &p_sbo) { // 'scrollopt'
- if (check_opt_strings(p_sbo, p_scbopt_values, true) != OK) {
- errmsg = e_invarg;
+ }
+}
+
+static void did_set_highlight(char **varp, char **errmsg)
+{
+ if (strcmp(*varp, HIGHLIGHT_INIT) != 0) {
+ *errmsg = e_unsupportedoption;
+ }
+}
+
+static void did_set_opt_flags(char *val, char **values, unsigned *flagp, bool list, char **errmsg)
+{
+ if (opt_strings_flags(val, values, flagp, list) != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_opt_strings(char *val, char **values, bool list, char **errmsg)
+{
+ did_set_opt_flags(val, values, NULL, list, errmsg);
+}
+
+static void did_set_sessionoptions(char *oldval, char **errmsg)
+{
+ if (opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, true) != OK) {
+ *errmsg = e_invarg;
+ }
+ if ((ssop_flags & SSOP_CURDIR) && (ssop_flags & SSOP_SESDIR)) {
+ // Don't allow both "sesdir" and "curdir".
+ (void)opt_strings_flags(oldval, p_ssop_values, &ssop_flags, true);
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_ambiwidth(char **errmsg)
+{
+ if (check_opt_strings(p_ambw, p_ambw_values, false) != OK) {
+ *errmsg = e_invarg;
+ } else {
+ *errmsg = check_chars_options();
+ }
+}
+
+static void did_set_background(char **errmsg)
+{
+ if (check_opt_strings(p_bg, p_bg_values, false) != OK) {
+ *errmsg = e_invarg;
+ return;
+ }
+
+ int dark = (*p_bg == 'd');
+
+ init_highlight(false, false);
+
+ if (dark != (*p_bg == 'd') && get_var_value("g:colors_name") != NULL) {
+ // The color scheme must have set 'background' back to another
+ // value, that's not what we want here. Disable the color
+ // scheme and set the colors again.
+ do_unlet(S_LEN("g:colors_name"), true);
+ free_string_option(p_bg);
+ p_bg = xstrdup((dark ? "dark" : "light"));
+ check_string_option(&p_bg);
+ init_highlight(false, false);
+ }
+}
+
+static void did_set_wildmode(char **errmsg)
+{
+ if (check_opt_wim() == FAIL) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_winaltkeys(char **errmsg)
+{
+ if (*p_wak == NUL || check_opt_strings(p_wak, p_wak_values, false) != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_eventignore(char **errmsg)
+{
+ if (check_ei() == FAIL) {
+ *errmsg = e_invarg;
+ }
+}
+
+// 'encoding', 'fileencoding' and 'makeencoding'
+static void did_set_encoding(buf_T *buf, char **varp, char **gvarp, int opt_flags, char **errmsg)
+{
+ if (gvarp == &p_fenc) {
+ if (!MODIFIABLE(buf) && opt_flags != OPT_GLOBAL) {
+ *errmsg = e_modifiable;
+ return;
}
- } else if (varp == &p_ambw || (int *)varp == &p_emoji) { // 'ambiwidth'
- if (check_opt_strings(p_ambw, p_ambw_values, false) != OK) {
- errmsg = e_invarg;
- } else {
- errmsg = check_chars_options();
- }
- } else if (varp == &p_bg) { // 'background'
- if (check_opt_strings(p_bg, p_bg_values, false) == OK) {
- int dark = (*p_bg == 'd');
-
- init_highlight(false, false);
-
- if (dark != (*p_bg == 'd') && get_var_value("g:colors_name") != NULL) {
- // The color scheme must have set 'background' back to another
- // value, that's not what we want here. Disable the color
- // scheme and set the colors again.
- do_unlet(S_LEN("g:colors_name"), true);
- free_string_option(p_bg);
- p_bg = xstrdup((dark ? "dark" : "light"));
- check_string_option(&p_bg);
- init_highlight(false, false);
- }
- } else {
- errmsg = e_invarg;
- }
- } else if (varp == &p_wim) { // 'wildmode'
- if (check_opt_wim() == FAIL) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_wop) { // 'wildoptions'
- if (opt_strings_flags(p_wop, p_wop_values, &wop_flags, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_wak) { // 'winaltkeys'
- if (*p_wak == NUL
- || check_opt_strings(p_wak, p_wak_values, false) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_ei) { // 'eventignore'
- if (check_ei() == FAIL) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_enc || gvarp == &p_fenc || gvarp == &p_menc) {
- // 'encoding', 'fileencoding' and 'makeencoding'
- if (gvarp == &p_fenc) {
- if (!MODIFIABLE(curbuf) && opt_flags != OPT_GLOBAL) {
- errmsg = e_modifiable;
- } else if (vim_strchr(*varp, ',') != NULL) {
- // No comma allowed in 'fileencoding'; catches confusing it
- // with 'fileencodings'.
- errmsg = e_invarg;
- } else {
- // May show a "+" in the title now.
- redraw_titles();
- // Add 'fileencoding' to the swap file.
- ml_setflags(curbuf);
- }
+
+ if (vim_strchr(*varp, ',') != NULL) {
+ // No comma allowed in 'fileencoding'; catches confusing it
+ // with 'fileencodings'.
+ *errmsg = e_invarg;
+ return;
}
- if (errmsg == NULL) {
- // canonize the value, so that strcmp() can be used on it
- p = enc_canonize(*varp);
- xfree(*varp);
- *varp = p;
- if (varp == &p_enc) {
- // only encoding=utf-8 allowed
- if (strcmp(p_enc, "utf-8") != 0) {
- errmsg = e_unsupportedoption;
- } else {
- spell_reload();
- }
- }
+ // May show a "+" in the title now.
+ redraw_titles();
+ // Add 'fileencoding' to the swap file.
+ ml_setflags(buf);
+ }
+
+ // canonize the value, so that strcmp() can be used on it
+ char *p = enc_canonize(*varp);
+ xfree(*varp);
+ *varp = p;
+ if (varp == &p_enc) {
+ // only encoding=utf-8 allowed
+ if (strcmp(p_enc, "utf-8") != 0) {
+ *errmsg = e_unsupportedoption;
+ return;
}
- } else if (varp == &curbuf->b_p_keymap) {
- if (!valid_filetype(*varp)) {
- errmsg = e_invarg;
- } else {
- int secure_save = secure;
+ spell_reload();
+ }
+}
+
+static void did_set_keymap(buf_T *buf, char **varp, int opt_flags, int *value_checked,
+ char **errmsg)
+{
+ if (!valid_filetype(*varp)) {
+ *errmsg = e_invarg;
+ return;
+ }
- // Reset the secure flag, since the value of 'keymap' has
- // been checked to be safe.
- secure = 0;
+ int secure_save = secure;
- // load or unload key mapping tables
- errmsg = keymap_init();
+ // Reset the secure flag, since the value of 'keymap' has
+ // been checked to be safe.
+ secure = 0;
- secure = secure_save;
+ // load or unload key mapping tables
+ *errmsg = keymap_init();
- // Since we check the value, there is no need to set P_INSECURE,
- // even when the value comes from a modeline.
- *value_checked = true;
- }
+ secure = secure_save;
- if (errmsg == NULL) {
- if (*curbuf->b_p_keymap != NUL) {
- // Installed a new keymap, switch on using it.
- curbuf->b_p_iminsert = B_IMODE_LMAP;
- if (curbuf->b_p_imsearch != B_IMODE_USE_INSERT) {
- curbuf->b_p_imsearch = B_IMODE_LMAP;
- }
- } else {
- // Cleared the keymap, may reset 'iminsert' and 'imsearch'.
- if (curbuf->b_p_iminsert == B_IMODE_LMAP) {
- curbuf->b_p_iminsert = B_IMODE_NONE;
- }
- if (curbuf->b_p_imsearch == B_IMODE_LMAP) {
- curbuf->b_p_imsearch = B_IMODE_USE_INSERT;
- }
- }
- if ((opt_flags & OPT_LOCAL) == 0) {
- set_iminsert_global();
- set_imsearch_global();
+ // Since we check the value, there is no need to set P_INSECURE,
+ // even when the value comes from a modeline.
+ *value_checked = true;
+
+ if (*errmsg == NULL) {
+ if (*buf->b_p_keymap != NUL) {
+ // Installed a new keymap, switch on using it.
+ buf->b_p_iminsert = B_IMODE_LMAP;
+ if (buf->b_p_imsearch != B_IMODE_USE_INSERT) {
+ buf->b_p_imsearch = B_IMODE_LMAP;
}
- status_redraw_curbuf();
- }
- } else if (gvarp == &p_ff) { // 'fileformat'
- if (!MODIFIABLE(curbuf) && !(opt_flags & OPT_GLOBAL)) {
- errmsg = e_modifiable;
- } else if (check_opt_strings(*varp, p_ff_values, false) != OK) {
- errmsg = e_invarg;
} else {
- redraw_titles();
- // update flag in swap file
- ml_setflags(curbuf);
- // Redraw needed when switching to/from "mac": a CR in the text
- // will be displayed differently.
- if (get_fileformat(curbuf) == EOL_MAC || *oldval == 'm') {
- redraw_curbuf_later(UPD_NOT_VALID);
+ // Cleared the keymap, may reset 'iminsert' and 'imsearch'.
+ if (buf->b_p_iminsert == B_IMODE_LMAP) {
+ buf->b_p_iminsert = B_IMODE_NONE;
+ }
+ if (buf->b_p_imsearch == B_IMODE_LMAP) {
+ buf->b_p_imsearch = B_IMODE_USE_INSERT;
}
}
- } else if (varp == &p_ffs) { // 'fileformats'
- if (check_opt_strings(p_ffs, p_ff_values, true) != OK) {
- errmsg = e_invarg;
+ if ((opt_flags & OPT_LOCAL) == 0) {
+ set_iminsert_global(buf);
+ set_imsearch_global(buf);
}
- } else if (gvarp == &p_mps) { // 'matchpairs'
- for (p = *varp; *p != NUL; p++) {
- int x2 = -1;
- int x3 = -1;
+ status_redraw_buf(buf);
+ }
+}
+
+static void did_set_fileformat(buf_T *buf, char **varp, const char *oldval, int opt_flags,
+ char **errmsg)
+{
+ if (!MODIFIABLE(buf) && !(opt_flags & OPT_GLOBAL)) {
+ *errmsg = e_modifiable;
+ } else if (check_opt_strings(*varp, p_ff_values, false) != OK) {
+ *errmsg = e_invarg;
+ } else {
+ redraw_titles();
+ // update flag in swap file
+ ml_setflags(buf);
+ // Redraw needed when switching to/from "mac": a CR in the text
+ // will be displayed differently.
+ if (get_fileformat(buf) == EOL_MAC || *oldval == 'm') {
+ redraw_buf_later(buf, UPD_NOT_VALID);
+ }
+ }
+}
+
+static void did_set_matchpairs(char **varp, char **errmsg)
+{
+ for (char *p = *varp; *p != NUL; p++) {
+ int x2 = -1;
+ int x3 = -1;
+ p += utfc_ptr2len(p);
+ if (*p != NUL) {
+ x2 = (unsigned char)(*p++);
+ }
+ if (*p != NUL) {
+ x3 = utf_ptr2char(p);
p += utfc_ptr2len(p);
- if (*p != NUL) {
- x2 = (unsigned char)(*p++);
- }
- if (*p != NUL) {
- x3 = utf_ptr2char(p);
- p += utfc_ptr2len(p);
- }
- if (x2 != ':' || x3 == -1 || (*p != NUL && *p != ',')) {
- errmsg = e_invarg;
- break;
- }
- if (*p == NUL) {
- break;
- }
}
- } else if (gvarp == &p_com) { // 'comments'
- for (s = *varp; *s;) {
- while (*s && *s != ':') {
- if (vim_strchr(COM_ALL, *s) == NULL
- && !ascii_isdigit(*s) && *s != '-') {
- errmsg = illegal_char(errbuf, errbuflen, *s);
- break;
- }
- s++;
- }
- if (*s++ == NUL) {
- errmsg = N_("E524: Missing colon");
- } else if (*s == ',' || *s == NUL) {
- errmsg = N_("E525: Zero length string");
- }
- if (errmsg != NULL) {
+ if (x2 != ':' || x3 == -1 || (*p != NUL && *p != ',')) {
+ *errmsg = e_invarg;
+ break;
+ }
+ if (*p == NUL) {
+ break;
+ }
+ }
+}
+
+static void did_set_comments(char **varp, char *errbuf, size_t errbuflen, char **errmsg)
+{
+ for (char *s = *varp; *s;) {
+ while (*s && *s != ':') {
+ if (vim_strchr(COM_ALL, (uint8_t)(*s)) == NULL
+ && !ascii_isdigit(*s) && *s != '-') {
+ *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s));
break;
}
- while (*s && *s != ',') {
- if (*s == '\\' && s[1] != NUL) {
- s++;
- }
+ s++;
+ }
+ if (*s++ == NUL) {
+ *errmsg = N_("E524: Missing colon");
+ } else if (*s == ',' || *s == NUL) {
+ *errmsg = N_("E525: Zero length string");
+ }
+ if (*errmsg != NULL) {
+ break;
+ }
+ while (*s && *s != ',') {
+ if (*s == '\\' && s[1] != NUL) {
s++;
}
- s = skip_to_option_part(s);
- }
- } else if (varp == &p_lcs || varp == &p_fcs) { // global 'listchars' or 'fillchars'
- char **local_ptr = varp == &p_lcs ? &curwin->w_p_lcs : &curwin->w_p_fcs;
- // only apply the global value to "curwin" when it does not have a local value
- errmsg =
- set_chars_option(curwin, varp, **local_ptr == NUL || !(opt_flags & OPT_GLOBAL));
- if (errmsg == NULL) {
- // If the current window is set to use the global
- // 'listchars'/'fillchars' value, clear the window-local value.
- if (!(opt_flags & OPT_GLOBAL)) {
- clear_string_option(local_ptr);
- }
- FOR_ALL_TAB_WINDOWS(tp, wp) {
- // If the current window has a local value need to apply it
- // again, it was changed when setting the global value.
- // If no error was returned above, we don't expect an error
- // here, so ignore the return value.
- local_ptr = varp == &p_lcs ? &wp->w_p_lcs : &wp->w_p_fcs;
- if (**local_ptr == NUL) {
- (void)set_chars_option(wp, local_ptr, true);
- }
- }
- redraw_all_later(UPD_NOT_VALID);
+ s++;
}
- } else if (varp == &curwin->w_p_lcs) { // local 'listchars'
- errmsg = set_chars_option(curwin, varp, true);
- } else if (varp == &curwin->w_p_fcs) { // local 'fillchars'
- errmsg = set_chars_option(curwin, varp, true);
- } else if (varp == &p_cedit) { // 'cedit'
- errmsg = check_cedit();
- } else if (varp == &p_vfile) { // 'verbosefile'
- verbose_stop();
- if (*p_vfile != NUL && verbose_open() == FAIL) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_shada) { // 'shada'
- // TODO(ZyX-I): Remove this code in the future, alongside with &viminfo
- // option.
- opt_idx = ((opt->fullname[0] == 'v')
- ? (shada_idx == -1 ? ((shada_idx = findoption("shada"))) : shada_idx)
- : opt_idx);
- opt = get_option(opt_idx);
- // Update free_oldval now that we have the opt_idx for 'shada', otherwise
- // there would be a disconnect between the check for P_ALLOCED at the start
- // of the function and the set of P_ALLOCED at the end of the function.
- free_oldval = (opt->flags & P_ALLOCED);
- for (s = p_shada; *s;) {
- // Check it's a valid character
- if (vim_strchr("!\"%'/:<@cfhnrs", *s) == NULL) {
- errmsg = illegal_char(errbuf, errbuflen, *s);
- break;
- }
- if (*s == 'n') { // name is always last one
- break;
- } else if (*s == 'r') { // skip until next ','
- while (*++s && *s != ',') {}
- } else if (*s == '%') {
- // optional number
- while (ascii_isdigit(*++s)) {}
- } else if (*s == '!' || *s == 'h' || *s == 'c') {
- s++; // no extra chars
- } else { // must have a number
- while (ascii_isdigit(*++s)) {}
-
- if (!ascii_isdigit(*(s - 1))) {
- if (errbuf != NULL) {
- vim_snprintf(errbuf, errbuflen,
- _("E526: Missing number after <%s>"),
- transchar_byte((uint8_t)(*(s - 1))));
- errmsg = errbuf;
- } else {
- errmsg = "";
- }
- break;
- }
+ s = skip_to_option_part(s);
+ }
+}
+
+static void did_set_global_listfillchars(win_T *win, char **varp, int opt_flags, char **errmsg)
+{
+ char **local_ptr = varp == &p_lcs ? &win->w_p_lcs : &win->w_p_fcs;
+ // only apply the global value to "win" when it does not have a local value
+ *errmsg = set_chars_option(win, varp, **local_ptr == NUL || !(opt_flags & OPT_GLOBAL));
+ if (*errmsg == NULL) {
+ // If the current window is set to use the global
+ // 'listchars'/'fillchars' value, clear the window-local value.
+ if (!(opt_flags & OPT_GLOBAL)) {
+ clear_string_option(local_ptr);
+ }
+ FOR_ALL_TAB_WINDOWS(tp, wp) {
+ // If the current window has a local value need to apply it
+ // again, it was changed when setting the global value.
+ // If no error was returned above, we don't expect an error
+ // here, so ignore the return value.
+ local_ptr = varp == &p_lcs ? &wp->w_p_lcs : &wp->w_p_fcs;
+ if (**local_ptr == NUL) {
+ (void)set_chars_option(wp, local_ptr, true);
}
- if (*s == ',') {
- s++;
- } else if (*s) {
+ }
+ redraw_all_later(UPD_NOT_VALID);
+ }
+}
+
+static void did_set_verbosefile(char **errmsg)
+{
+ verbose_stop();
+ if (*p_vfile != NUL && verbose_open() == FAIL) {
+ *errmsg = e_invarg;
+ }
+}
+
+static int shada_idx = -1;
+
+static void did_set_shada(vimoption_T **opt, int *opt_idx, bool *free_oldval, char *errbuf,
+ size_t errbuflen, char **errmsg)
+{
+ // TODO(ZyX-I): Remove this code in the future, alongside with &viminfo
+ // option.
+ *opt_idx = (((*opt)->fullname[0] == 'v')
+ ? (shada_idx == -1 ? ((shada_idx = findoption("shada"))) : shada_idx)
+ : *opt_idx);
+ *opt = get_option(*opt_idx);
+ // Update free_oldval now that we have the opt_idx for 'shada', otherwise
+ // there would be a disconnect between the check for P_ALLOCED at the start
+ // of the function and the set of P_ALLOCED at the end of the function.
+ *free_oldval = ((*opt)->flags & P_ALLOCED);
+ for (char *s = p_shada; *s;) {
+ // Check it's a valid character
+ if (vim_strchr("!\"%'/:<@cfhnrs", (uint8_t)(*s)) == NULL) {
+ *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s));
+ break;
+ }
+ if (*s == 'n') { // name is always last one
+ break;
+ } else if (*s == 'r') { // skip until next ','
+ while (*++s && *s != ',') {}
+ } else if (*s == '%') {
+ // optional number
+ while (ascii_isdigit(*++s)) {}
+ } else if (*s == '!' || *s == 'h' || *s == 'c') {
+ s++; // no extra chars
+ } else { // must have a number
+ while (ascii_isdigit(*++s)) {}
+
+ if (!ascii_isdigit(*(s - 1))) {
if (errbuf != NULL) {
- errmsg = N_("E527: Missing comma");
+ vim_snprintf(errbuf, errbuflen,
+ _("E526: Missing number after <%s>"),
+ transchar_byte((uint8_t)(*(s - 1))));
+ *errmsg = errbuf;
} else {
- errmsg = "";
+ *errmsg = "";
}
break;
}
}
- if (*p_shada && errmsg == NULL && get_shada_parameter('\'') < 0) {
- errmsg = N_("E528: Must specify a ' value");
- }
- } else if (gvarp == &p_sbr) { // 'showbreak'
- for (s = *varp; *s;) {
- if (ptr2cells(s) != 1) {
- errmsg = e_showbreak_contains_unprintable_or_wide_character;
+ if (*s == ',') {
+ s++;
+ } else if (*s) {
+ if (errbuf != NULL) {
+ *errmsg = N_("E527: Missing comma");
+ } else {
+ *errmsg = "";
}
- MB_PTR_ADV(s);
+ break;
}
- } else if (varp == &p_guicursor) { // 'guicursor'
- errmsg = parse_shape_opt(SHAPE_CURSOR);
- } else if (varp == &p_langmap) { // 'langmap'
- langmap_set();
- } else if (varp == &p_breakat) { // 'breakat'
- fill_breakat_flags();
- } else if (varp == &p_titlestring || varp == &p_iconstring) {
- // 'titlestring' and 'iconstring'
- int flagval = (varp == &p_titlestring) ? STL_IN_TITLE : STL_IN_ICON;
+ }
+ if (*p_shada && *errmsg == NULL && get_shada_parameter('\'') < 0) {
+ *errmsg = N_("E528: Must specify a ' value");
+ }
+}
- // NULL => statusline syntax
- if (vim_strchr(*varp, '%') && check_stl_option(*varp) == NULL) {
- stl_syntax |= flagval;
- } else {
- stl_syntax &= ~flagval;
+static void did_set_showbreak(char **varp, char **errmsg)
+{
+ for (char *s = *varp; *s;) {
+ if (ptr2cells(s) != 1) {
+ *errmsg = e_showbreak_contains_unprintable_or_wide_character;
}
- did_set_title();
- } else if (varp == &p_sel) { // 'selection'
- if (*p_sel == NUL
- || check_opt_strings(p_sel, p_sel_values, false) != OK) {
- errmsg = e_invarg;
+ MB_PTR_ADV(s);
+ }
+}
+
+static void did_set_titleiconstring(char **varp)
+{
+ // 'titlestring' and 'iconstring'
+ int flagval = (varp == &p_titlestring) ? STL_IN_TITLE : STL_IN_ICON;
+
+ // NULL => statusline syntax
+ if (vim_strchr(*varp, '%') && check_stl_option(*varp) == NULL) {
+ stl_syntax |= flagval;
+ } else {
+ stl_syntax &= ~flagval;
+ }
+ did_set_title();
+}
+
+static void did_set_selection(char **errmsg)
+{
+ if (*p_sel == NUL || check_opt_strings(p_sel, p_sel_values, false) != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_keymodel(char **errmsg)
+{
+ if (check_opt_strings(p_km, p_km_values, true) != OK) {
+ *errmsg = e_invarg;
+ return;
+ }
+ km_stopsel = (vim_strchr(p_km, 'o') != NULL);
+ km_startsel = (vim_strchr(p_km, 'a') != NULL);
+}
+
+static void did_set_display(char **errmsg)
+{
+ if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, true) != OK) {
+ *errmsg = e_invarg;
+ return;
+ }
+ (void)init_chartab();
+ msg_grid_validate();
+}
+
+static void did_set_spellfile(char **varp, char **errmsg)
+{
+ // When there is a window for this buffer in which 'spell'
+ // is set load the wordlists.
+
+ if ((!valid_spellfile(*varp))) {
+ *errmsg = e_invarg;
+ } else {
+ *errmsg = did_set_spell_option(true);
+ }
+}
+
+static void did_set_spell(char **varp, char **errmsg)
+{
+ // When there is a window for this buffer in which 'spell'
+ // is set load the wordlists.
+ if (!valid_spelllang(*varp)) {
+ *errmsg = e_invarg;
+ } else {
+ *errmsg = did_set_spell_option(false);
+ }
+}
+
+static void did_set_spellcapcheck(win_T *win, char **errmsg)
+{
+ // When 'spellcapcheck' is set compile the regexp program.
+ *errmsg = compile_cap_prog(win->w_s);
+}
+
+static void did_set_spelloptions(win_T *win, char **errmsg)
+{
+ if (opt_strings_flags(win->w_s->b_p_spo, p_spo_values, &(win->w_s->b_p_spo_flags),
+ true) != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_spellsuggest(char **errmsg)
+{
+ if (spell_check_sps() != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_mkspellmem(char **errmsg)
+{
+ if (spell_check_msm() != OK) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_buftype(buf_T *buf, win_T *win, char **errmsg)
+{
+ // When 'buftype' is set, check for valid value.
+ if ((buf->terminal && buf->b_p_bt[0] != 't')
+ || (!buf->terminal && buf->b_p_bt[0] == 't')
+ || check_opt_strings(buf->b_p_bt, p_buftype_values, false) != OK) {
+ *errmsg = e_invarg;
+ } else {
+ if (win->w_status_height || global_stl_height()) {
+ win->w_redr_status = true;
+ redraw_later(win, UPD_VALID);
}
- } else if (varp == &p_slm) { // 'selectmode'
- if (check_opt_strings(p_slm, p_slm_values, true) != OK) {
- errmsg = e_invarg;
+ buf->b_help = (buf->b_p_bt[0] == 'h');
+ redraw_titles();
+ }
+}
+
+// 'statusline', 'winbar', 'tabline', 'rulerformat' or 'statuscolumn'
+static void did_set_statusline(win_T *win, char **varp, char **gvarp, char **errmsg)
+{
+ if (varp == &p_ruf) { // reset ru_wid first
+ ru_wid = 0;
+ } else if (varp == &win->w_p_stc) {
+ win->w_nrwidth_line_count = 0;
+ }
+ char *s = *varp;
+ if (varp == &p_ruf && *s == '%') {
+ // set ru_wid if 'ruf' starts with "%99("
+ if (*++s == '-') { // ignore a '-'
+ s++;
}
- } else if (varp == &p_km) { // 'keymodel'
- if (check_opt_strings(p_km, p_km_values, true) != OK) {
- errmsg = e_invarg;
+ int wid = getdigits_int(&s, true, 0);
+ if (wid && *s == '(' && (*errmsg = check_stl_option(p_ruf)) == NULL) {
+ ru_wid = wid;
} else {
- km_stopsel = (vim_strchr(p_km, 'o') != NULL);
- km_startsel = (vim_strchr(p_km, 'a') != NULL);
+ *errmsg = check_stl_option(p_ruf);
}
- } else if (varp == &p_mousem) { // 'mousemodel'
- if (check_opt_strings(p_mousem, p_mousem_values, false) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_mousescroll) { // 'mousescroll'
- errmsg = check_mousescroll(p_mousescroll);
- } else if (varp == &p_swb) { // 'switchbuf'
- if (opt_strings_flags(p_swb, p_swb_values, &swb_flags, true) != OK) {
- errmsg = e_invarg;
+ } else if (varp == &p_ruf || s[0] != '%' || s[1] != '!') {
+ // check 'statusline', 'winbar', 'tabline' or 'statuscolumn'
+ // only if it doesn't start with "%!"
+ *errmsg = check_stl_option(s);
+ }
+ if (varp == &p_ruf && *errmsg == NULL) {
+ comp_col();
+ }
+ // add / remove window bars for 'winbar'
+ if (gvarp == &p_wbr) {
+ set_winbar(true);
+ }
+}
+
+static void did_set_complete(char **varp, char *errbuf, size_t errbuflen, char **errmsg)
+{
+ // check if it is a valid value for 'complete' -- Acevedo
+ for (char *s = *varp; *s;) {
+ while (*s == ',' || *s == ' ') {
+ s++;
}
- } else if (varp == &p_spk) { // 'splitkeep'
- if (check_opt_strings(p_spk, p_spk_values, false) != OK) {
- errmsg = e_invarg;
+ if (!*s) {
+ break;
}
- } else if (varp == &p_debug) { // 'debug'
- if (check_opt_strings(p_debug, p_debug_values, true) != OK) {
- errmsg = e_invarg;
+ if (vim_strchr(".wbuksid]tU", (uint8_t)(*s)) == NULL) {
+ *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s));
+ break;
}
- } else if (varp == &p_dy) { // 'display'
- if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, true) != OK) {
- errmsg = e_invarg;
- } else {
- (void)init_chartab();
- msg_grid_validate();
- }
- } else if (varp == &p_ead) { // 'eadirection'
- if (check_opt_strings(p_ead, p_ead_values, false) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_cb) { // 'clipboard'
- if (opt_strings_flags(p_cb, p_cb_values, &cb_flags, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &(curwin->w_s->b_p_spl) // 'spell'
- || varp == &(curwin->w_s->b_p_spf)) {
- // When 'spelllang' or 'spellfile' is set and there is a window for this
- // buffer in which 'spell' is set load the wordlists.
- const bool is_spellfile = varp == &(curwin->w_s->b_p_spf);
-
- if ((is_spellfile && !valid_spellfile(*varp))
- || (!is_spellfile && !valid_spelllang(*varp))) {
- errmsg = e_invarg;
- } else {
- errmsg = did_set_spell_option(is_spellfile);
- }
- } else if (varp == &(curwin->w_s->b_p_spc)) {
- // When 'spellcapcheck' is set compile the regexp program.
- errmsg = compile_cap_prog(curwin->w_s);
- } else if (varp == &(curwin->w_s->b_p_spo)) { // 'spelloptions'
- if (opt_strings_flags(curwin->w_s->b_p_spo, p_spo_values, &(curwin->w_s->b_p_spo_flags),
- true) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_sps) { // 'spellsuggest'
- if (spell_check_sps() != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_msm) { // 'mkspellmem'
- if (spell_check_msm() != OK) {
- errmsg = e_invarg;
- }
- } else if (gvarp == &p_bh) {
- // When 'bufhidden' is set, check for valid value.
- if (check_opt_strings(curbuf->b_p_bh, p_bufhidden_values, false) != OK) {
- errmsg = e_invarg;
- }
- } else if (gvarp == &p_bt) {
- // When 'buftype' is set, check for valid value.
- if ((curbuf->terminal && curbuf->b_p_bt[0] != 't')
- || (!curbuf->terminal && curbuf->b_p_bt[0] == 't')
- || check_opt_strings(curbuf->b_p_bt, p_buftype_values, false) != OK) {
- errmsg = e_invarg;
- } else {
- if (curwin->w_status_height || global_stl_height()) {
- curwin->w_redr_status = true;
- redraw_later(curwin, UPD_VALID);
- }
- curbuf->b_help = (curbuf->b_p_bt[0] == 'h');
- redraw_titles();
- }
- } else if (gvarp == &p_stl || gvarp == &p_wbr || varp == &p_tal
- || varp == &p_ruf || varp == &curwin->w_p_stc) {
- // 'statusline', 'winbar', 'tabline', 'rulerformat' or 'statuscolumn'
- int wid;
-
- if (varp == &p_ruf) { // reset ru_wid first
- ru_wid = 0;
- } else if (varp == &curwin->w_p_stc) {
- curwin->w_nrwidth_line_count = 0;
- }
- s = *varp;
- if (varp == &p_ruf && *s == '%') {
- // set ru_wid if 'ruf' starts with "%99("
- if (*++s == '-') { // ignore a '-'
- s++;
- }
- wid = getdigits_int(&s, true, 0);
- if (wid && *s == '(' && (errmsg = check_stl_option(p_ruf)) == NULL) {
- ru_wid = wid;
- } else {
- errmsg = check_stl_option(p_ruf);
- }
- } else if (varp == &p_ruf || s[0] != '%' || s[1] != '!') {
- // check 'statusline', 'winbar', 'tabline' or 'statuscolumn'
- // only if it doesn't start with "%!"
- errmsg = check_stl_option(s);
- }
- if (varp == &p_ruf && errmsg == NULL) {
- comp_col();
- }
- // add / remove window bars for 'winbar'
- if (gvarp == &p_wbr) {
- set_winbar(true);
- }
- } else if (gvarp == &p_cpt) {
- // check if it is a valid value for 'complete' -- Acevedo
- for (s = *varp; *s;) {
- while (*s == ',' || *s == ' ') {
- s++;
- }
- if (!*s) {
- break;
- }
- if (vim_strchr(".wbuksid]tU", *s) == NULL) {
- errmsg = illegal_char(errbuf, errbuflen, *s);
- break;
- }
- if (*++s != NUL && *s != ',' && *s != ' ') {
- if (s[-1] == 'k' || s[-1] == 's') {
- // skip optional filename after 'k' and 's'
- while (*s && *s != ',' && *s != ' ') {
- if (*s == '\\' && s[1] != NUL) {
- s++;
- }
+ if (*++s != NUL && *s != ',' && *s != ' ') {
+ if (s[-1] == 'k' || s[-1] == 's') {
+ // skip optional filename after 'k' and 's'
+ while (*s && *s != ',' && *s != ' ') {
+ if (*s == '\\' && s[1] != NUL) {
s++;
}
+ s++;
+ }
+ } else {
+ if (errbuf != NULL) {
+ vim_snprintf(errbuf, errbuflen,
+ _("E535: Illegal character after <%c>"),
+ *--s);
+ *errmsg = errbuf;
} else {
- if (errbuf != NULL) {
- vim_snprintf(errbuf, errbuflen,
- _("E535: Illegal character after <%c>"),
- *--s);
- errmsg = errbuf;
- } else {
- errmsg = "";
- }
- break;
+ *errmsg = "";
}
+ break;
}
}
- } else if (varp == &p_cot) { // 'completeopt'
- if (check_opt_strings(p_cot, p_cot_values, true) != OK) {
- errmsg = e_invarg;
- } else {
- completeopt_was_set();
- }
+ }
+}
+
+static void did_set_completeopt(char **errmsg)
+{
+ if (check_opt_strings(p_cot, p_cot_values, true) != OK) {
+ *errmsg = e_invarg;
+ } else {
+ completeopt_was_set();
+ }
+}
+
#ifdef BACKSLASH_IN_FILENAME
- } else if (gvarp == &p_csl) { // 'completeslash'
- if (check_opt_strings(p_csl, p_csl_values, false) != OK
- || check_opt_strings(curbuf->b_p_csl, p_csl_values, false) != OK) {
- errmsg = e_invarg;
- }
+static void did_set_completeslash(buf_T *buf, char **errmsg)
+{
+ if (check_opt_strings(p_csl, p_csl_values, false) != OK
+ || check_opt_strings(buf->b_p_csl, p_csl_values, false) != OK) {
+ *errmsg = e_invarg;
+ }
+}
#endif
- } else if (varp == &curwin->w_p_scl) { // 'signcolumn'
- if (check_signcolumn(*varp) != OK) {
- errmsg = e_invarg;
- }
- // When changing the 'signcolumn' to or from 'number', recompute the
- // width of the number column if 'number' or 'relativenumber' is set.
- if (((*oldval == 'n' && *(oldval + 1) == 'u')
- || (*curwin->w_p_scl == 'n' && *(curwin->w_p_scl + 1) == 'u'))
- && (curwin->w_p_nu || curwin->w_p_rnu)) {
- curwin->w_nrwidth_line_count = 0;
- }
- } else if (varp == &p_sloc) { // 'showcmdloc'
- if (check_opt_strings(p_sloc, p_sloc_values, false) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &curwin->w_p_fdc
- || varp == &curwin->w_allbuf_opt.wo_fdc) {
- // 'foldcolumn'
- if (**varp == NUL || check_opt_strings(*varp, p_fdc_values, false) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_pt) {
- // 'pastetoggle': translate key codes like in a mapping
- if (*p_pt) {
- p = NULL;
- (void)replace_termcodes(p_pt,
- strlen(p_pt),
- &p, REPTERM_FROM_PART | REPTERM_DO_LT, NULL,
- CPO_TO_CPO_FLAGS);
- if (p != NULL) {
- free_string_option(p_pt);
- p_pt = p;
- }
- }
- } else if (varp == &p_bs) { // 'backspace'
- if (ascii_isdigit(*p_bs)) {
- if (*p_bs > '3' || p_bs[1] != NUL) {
- errmsg = e_invarg;
- }
- } else if (check_opt_strings(p_bs, p_bs_values, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_bo) {
- if (opt_strings_flags(p_bo, p_bo_values, &bo_flags, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (gvarp == &p_tc) { // 'tagcase'
- unsigned int *flags;
- if (opt_flags & OPT_LOCAL) {
- p = curbuf->b_p_tc;
- flags = &curbuf->b_tc_flags;
- } else {
- p = p_tc;
- flags = &tc_flags;
- }
+static void did_set_signcolumn(win_T *win, char **varp, const char *oldval, char **errmsg)
+{
+ if (check_signcolumn(*varp) != OK) {
+ *errmsg = e_invarg;
+ }
+ // When changing the 'signcolumn' to or from 'number', recompute the
+ // width of the number column if 'number' or 'relativenumber' is set.
+ if (((*oldval == 'n' && *(oldval + 1) == 'u')
+ || (*win->w_p_scl == 'n' && *(win->w_p_scl + 1) == 'u'))
+ && (win->w_p_nu || win->w_p_rnu)) {
+ win->w_nrwidth_line_count = 0;
+ }
+}
- if ((opt_flags & OPT_LOCAL) && *p == NUL) {
- // make the local value empty: use the global value
- *flags = 0;
- } else if (*p == NUL
- || opt_strings_flags(p, p_tc_values, flags, false) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_cmp) { // 'casemap'
- if (opt_strings_flags(p_cmp, p_cmp_values, &cmp_flags, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_dip) { // 'diffopt'
- if (diffopt_changed() == FAIL) {
- errmsg = e_invarg;
- }
- } else if (gvarp == &curwin->w_allbuf_opt.wo_fdm) { // 'foldmethod'
- if (check_opt_strings(*varp, p_fdm_values, false) != OK
- || *curwin->w_p_fdm == NUL) {
- errmsg = e_invarg;
- } else {
- foldUpdateAll(curwin);
- if (foldmethodIsDiff(curwin)) {
- newFoldLevel();
- }
- }
- } else if (gvarp == &curwin->w_allbuf_opt.wo_fmr) { // 'foldmarker'
- p = vim_strchr(*varp, ',');
- if (p == NULL) {
- errmsg = N_("E536: comma required");
- } else if (p == *varp || p[1] == NUL) {
- errmsg = e_invarg;
- } else if (foldmethodIsMarker(curwin)) {
- foldUpdateAll(curwin);
- }
- } else if (gvarp == &p_cms) { // 'commentstring'
- if (**varp != NUL && strstr(*varp, "%s") == NULL) {
- errmsg = N_("E537: 'commentstring' must be empty or contain %s");
- }
- } else if (varp == &p_fdo) { // 'foldopen'
- if (opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_fcl) { // 'foldclose'
- if (check_opt_strings(p_fcl, p_fcl_values, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (gvarp == &curwin->w_allbuf_opt.wo_fdi) { // 'foldignore'
- if (foldmethodIsIndent(curwin)) {
- foldUpdateAll(curwin);
- }
- } else if (gvarp == &p_ve) { // 'virtualedit'
- char *ve = p_ve;
- unsigned int *flags = &ve_flags;
+static void did_set_foldcolumn(char **varp, char **errmsg)
+{
+ if (**varp == NUL || check_opt_strings(*varp, p_fdc_values, false) != OK) {
+ *errmsg = e_invarg;
+ }
+}
- if (opt_flags & OPT_LOCAL) {
- ve = curwin->w_p_ve;
- flags = &curwin->w_ve_flags;
+static void did_set_pastetoggle(void)
+{
+ // 'pastetoggle': translate key codes like in a mapping
+ if (*p_pt) {
+ char *p = NULL;
+ (void)replace_termcodes(p_pt,
+ strlen(p_pt),
+ &p, REPTERM_FROM_PART | REPTERM_DO_LT, NULL,
+ CPO_TO_CPO_FLAGS);
+ if (p != NULL) {
+ free_string_option(p_pt);
+ p_pt = p;
}
+ }
+}
- if ((opt_flags & OPT_LOCAL) && *ve == NUL) {
- // make the local value empty: use the global value
- *flags = 0;
- } else {
- if (opt_strings_flags(ve, p_ve_values, flags, true) != OK) {
- errmsg = e_invarg;
- } else if (strcmp(p_ve, oldval) != 0) {
- // Recompute cursor position in case the new 've' setting
- // changes something.
- validate_virtcol();
- coladvance(curwin->w_virtcol);
- }
+static void did_set_backspace(char **errmsg)
+{
+ if (ascii_isdigit(*p_bs)) {
+ if (*p_bs > '3' || p_bs[1] != NUL) {
+ *errmsg = e_invarg;
}
- } else if (gvarp == &p_cino) { // 'cinoptions'
- // TODO(vim): recognize errors
- parse_cino(curbuf);
- } else if (gvarp == &p_lop) { // 'lispoptions'
- if (**varp != NUL && strcmp(*varp, "expr:0") != 0 && strcmp(*varp, "expr:1") != 0) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_icm) { // 'inccommand'
- if (check_opt_strings(p_icm, p_icm_values, false) != OK) {
- errmsg = e_invarg;
- }
- } else if (gvarp == &p_ft) {
- if (!valid_filetype(*varp)) {
- errmsg = e_invarg;
- } else {
- value_changed = strcmp(oldval, *varp) != 0;
+ } else if (check_opt_strings(p_bs, p_bs_values, true) != OK) {
+ *errmsg = e_invarg;
+ }
+}
- // Since we check the value, there is no need to set P_INSECURE,
- // even when the value comes from a modeline.
- *value_checked = true;
- }
- } else if (gvarp == &p_syn) {
- if (!valid_filetype(*varp)) {
- errmsg = e_invarg;
- } else {
- value_changed = strcmp(oldval, *varp) != 0;
+static void did_set_tagcase(buf_T *buf, int opt_flags, char **errmsg)
+{
+ unsigned int *flags;
+ char *p;
- // Since we check the value, there is no need to set P_INSECURE,
- // even when the value comes from a modeline.
- *value_checked = true;
- }
- } else if (varp == &curwin->w_p_winhl) {
- if (!parse_winhl_opt(curwin)) {
- errmsg = e_invarg;
- }
- } else if (varp == &p_tpf) {
- if (opt_strings_flags(p_tpf, p_tpf_values, &tpf_flags, true) != OK) {
- errmsg = e_invarg;
- }
- } else if (varp == &(curbuf->b_p_vsts)) { // 'varsofttabstop'
- char *cp;
+ if (opt_flags & OPT_LOCAL) {
+ p = buf->b_p_tc;
+ flags = &buf->b_tc_flags;
+ } else {
+ p = p_tc;
+ flags = &tc_flags;
+ }
- if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) {
- XFREE_CLEAR(curbuf->b_p_vsts_array);
- } else {
- for (cp = *varp; *cp; cp++) {
- if (ascii_isdigit(*cp)) {
- continue;
- }
- if (*cp == ',' && cp > *varp && *(cp - 1) != ',') {
- continue;
- }
- errmsg = e_invarg;
- break;
- }
- if (errmsg == NULL) {
- long *oldarray = curbuf->b_p_vsts_array;
- if (tabstop_set(*varp, &(curbuf->b_p_vsts_array))) {
- xfree(oldarray);
- } else {
- errmsg = e_invarg;
- }
- }
- }
- } else if (varp == &(curbuf->b_p_vts)) { // 'vartabstop'
- char *cp;
+ if ((opt_flags & OPT_LOCAL) && *p == NUL) {
+ // make the local value empty: use the global value
+ *flags = 0;
+ } else if (*p == NUL
+ || opt_strings_flags(p, p_tc_values, flags, false) != OK) {
+ *errmsg = e_invarg;
+ }
+}
- if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) {
- XFREE_CLEAR(curbuf->b_p_vts_array);
- } else {
- for (cp = *varp; *cp; cp++) {
- if (ascii_isdigit(*cp)) {
- continue;
- }
- if (*cp == ',' && cp > *varp && *(cp - 1) != ',') {
- continue;
- }
- errmsg = e_invarg;
- break;
- }
- if (errmsg == NULL) {
- long *oldarray = curbuf->b_p_vts_array;
- if (tabstop_set(*varp, &(curbuf->b_p_vts_array))) {
- xfree(oldarray);
- if (foldmethodIsIndent(curwin)) {
- foldUpdateAll(curwin);
- }
- } else {
- errmsg = e_invarg;
- }
- }
+static void did_set_diffopt(char **errmsg)
+{
+ if (diffopt_changed() == FAIL) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_foldmethod(win_T *win, char **varp, char **errmsg)
+{
+ if (check_opt_strings(*varp, p_fdm_values, false) != OK
+ || *win->w_p_fdm == NUL) {
+ *errmsg = e_invarg;
+ } else {
+ foldUpdateAll(win);
+ if (foldmethodIsDiff(win)) {
+ newFoldLevel();
}
- } else if (varp == &p_dex
- || varp == &curwin->w_p_fde
- || varp == &curwin->w_p_fdt
- || gvarp == &p_fex
- || gvarp == &p_inex
- || gvarp == &p_inde
- || varp == &p_pex) { // '*expr' options
- char **p_opt = NULL;
+ }
+}
- // If the option value starts with <SID> or s:, then replace that with
- // the script identifier.
+static void did_set_foldmarker(win_T *win, char **varp, char **errmsg)
+{
+ char *p = vim_strchr(*varp, ',');
+ if (p == NULL) {
+ *errmsg = N_("E536: comma required");
+ } else if (p == *varp || p[1] == NUL) {
+ *errmsg = e_invarg;
+ } else if (foldmethodIsMarker(win)) {
+ foldUpdateAll(win);
+ }
+}
- if (varp == &p_dex) { // 'diffexpr'
- p_opt = &p_dex;
- }
- if (varp == &curwin->w_p_fde) { // 'foldexpr'
- p_opt = &curwin->w_p_fde;
- }
- if (varp == &curwin->w_p_fdt) { // 'foldtext'
- p_opt = &curwin->w_p_fdt;
- }
- if (gvarp == &p_fex) { // 'formatexpr'
- p_opt = &curbuf->b_p_fex;
- }
- if (gvarp == &p_inex) { // 'includeexpr'
- p_opt = &curbuf->b_p_inex;
- }
- if (gvarp == &p_inde) { // 'indentexpr'
- p_opt = &curbuf->b_p_inde;
- }
- if (varp == &p_pex) { // 'patchexpr'
- p_opt = &p_pex;
- }
+static void did_set_commentstring(char **varp, char **errmsg)
+{
+ if (**varp != NUL && strstr(*varp, "%s") == NULL) {
+ *errmsg = N_("E537: 'commentstring' must be empty or contain %s");
+ }
+}
- if (p_opt != NULL) {
- char *name = get_scriptlocal_funcname(*p_opt);
- if (name != NULL) {
- free_string_option(*p_opt);
- *p_opt = name;
- }
- }
+static void did_set_foldignore(win_T *win)
+{
+ if (foldmethodIsIndent(win)) {
+ foldUpdateAll(win);
+ }
+}
- if (varp == &curwin->w_p_fde && foldmethodIsExpr(curwin)) {
- foldUpdateAll(curwin);
- }
- } else if (gvarp == &p_cfu) { // 'completefunc'
- if (set_completefunc_option() == FAIL) {
- errmsg = e_invarg;
+static void did_set_virtualedit(win_T *win, int opt_flags, char *oldval, char **errmsg)
+{
+ char *ve = p_ve;
+ unsigned int *flags = &ve_flags;
+
+ if (opt_flags & OPT_LOCAL) {
+ ve = win->w_p_ve;
+ flags = &win->w_ve_flags;
+ }
+
+ if ((opt_flags & OPT_LOCAL) && *ve == NUL) {
+ // make the local value empty: use the global value
+ *flags = 0;
+ } else {
+ if (opt_strings_flags(ve, p_ve_values, flags, true) != OK) {
+ *errmsg = e_invarg;
+ } else if (strcmp(ve, oldval) != 0) {
+ // Recompute cursor position in case the new 've' setting
+ // changes something.
+ validate_virtcol_win(win);
+ // XXX: this only works when win == curwin
+ coladvance(win->w_virtcol);
}
- } else if (gvarp == &p_ofu) { // 'omnifunc'
- if (set_omnifunc_option() == FAIL) {
- errmsg = e_invarg;
+ }
+}
+
+static void did_set_lispoptions(char **varp, char **errmsg)
+{
+ if (**varp != NUL && strcmp(*varp, "expr:0") != 0 && strcmp(*varp, "expr:1") != 0) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_filetype_or_syntax(char **varp, char *oldval, int *value_checked,
+ bool *value_changed, char **errmsg)
+{
+ if (!valid_filetype(*varp)) {
+ *errmsg = e_invarg;
+ return;
+ }
+
+ *value_changed = strcmp(oldval, *varp) != 0;
+
+ // Since we check the value, there is no need to set P_INSECURE,
+ // even when the value comes from a modeline.
+ *value_checked = true;
+}
+
+static void did_set_winhl(win_T *win, char **errmsg)
+{
+ if (!parse_winhl_opt(win)) {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_varsoftabstop(buf_T *buf, char **varp, char **errmsg)
+{
+ if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) {
+ XFREE_CLEAR(buf->b_p_vsts_array);
+ return;
+ }
+
+ for (char *cp = *varp; *cp; cp++) {
+ if (ascii_isdigit(*cp)) {
+ continue;
}
- } else if (gvarp == &p_tsrfu) { // 'thesaurusfunc'
- if (set_thesaurusfunc_option() == FAIL) {
- errmsg = e_invarg;
+ if (*cp == ',' && cp > *varp && *(cp - 1) != ',') {
+ continue;
}
- } else if (varp == &p_opfunc) { // 'operatorfunc'
- if (set_operatorfunc_option() == FAIL) {
- errmsg = e_invarg;
+ *errmsg = e_invarg;
+ return;
+ }
+
+ long *oldarray = buf->b_p_vsts_array;
+ if (tabstop_set(*varp, &(buf->b_p_vsts_array))) {
+ xfree(oldarray);
+ } else {
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_vartabstop(buf_T *buf, win_T *win, char **varp, char **errmsg)
+{
+ if (!(*varp)[0] || ((*varp)[0] == '0' && !(*varp)[1])) {
+ XFREE_CLEAR(buf->b_p_vts_array);
+ return;
+ }
+
+ for (char *cp = *varp; *cp; cp++) {
+ if (ascii_isdigit(*cp)) {
+ continue;
}
- } else if (varp == &p_qftf) { // 'quickfixtextfunc'
- if (qf_process_qftf_option() == FAIL) {
- errmsg = e_invarg;
+ if (*cp == ',' && cp > *varp && *(cp - 1) != ',') {
+ continue;
}
- } else if (gvarp == &p_tfu) { // 'tagfunc'
- if (set_tagfunc_option() == FAIL) {
- errmsg = e_invarg;
+ *errmsg = e_invarg;
+ return;
+ }
+
+ long *oldarray = buf->b_p_vts_array;
+ if (tabstop_set(*varp, &(buf->b_p_vts_array))) {
+ xfree(oldarray);
+ if (foldmethodIsIndent(win)) {
+ foldUpdateAll(win);
}
} else {
- // Options that are a list of flags.
- p = NULL;
- if (varp == &p_ww) { // 'whichwrap'
- p = WW_ALL;
- }
- if (varp == &p_shm) { // 'shortmess'
- p = SHM_ALL;
- } else if (varp == &(p_cpo)) { // 'cpoptions'
- p = CPO_VI;
- } else if (varp == &(curbuf->b_p_fo)) { // 'formatoptions'
- p = FO_ALL;
- } else if (varp == &curwin->w_p_cocu) { // 'concealcursor'
- p = COCU_ALL;
- } else if (varp == &p_mouse) { // 'mouse'
- p = MOUSE_ALL;
+ *errmsg = e_invarg;
+ }
+}
+
+static void did_set_optexpr(char **varp)
+{
+ char *name = get_scriptlocal_funcname(*varp);
+ if (name != NULL) {
+ free_string_option(*varp);
+ *varp = name;
+ }
+}
+
+// handle option that is a list of flags.
+static void did_set_option_listflag(char **varp, char *flags, char *errbuf, size_t errbuflen,
+ char **errmsg)
+{
+ for (char *s = *varp; *s; s++) {
+ if (vim_strchr(flags, (uint8_t)(*s)) == NULL) {
+ *errmsg = illegal_char(errbuf, errbuflen, (uint8_t)(*s));
+ break;
}
- if (p != NULL) {
- for (s = *varp; *s; s++) {
- if (vim_strchr(p, *s) == NULL) {
- errmsg = illegal_char(errbuf, errbuflen, *s);
- break;
- }
- }
+ }
+}
+
+// When 'syntax' is set, load the syntax of that name
+static void do_syntax_autocmd(buf_T *buf, bool value_changed)
+{
+ static int syn_recursive = 0;
+
+ syn_recursive++;
+ // Only pass true for "force" when the value changed or not used
+ // recursively, to avoid endless recurrence.
+ apply_autocmds(EVENT_SYNTAX, buf->b_p_syn, buf->b_fname,
+ value_changed || syn_recursive == 1, buf);
+ buf->b_flags |= BF_SYN_SET;
+ syn_recursive--;
+}
+
+static void do_filetype_autocmd(buf_T *buf, char **varp, int opt_flags, bool value_changed)
+{
+ // 'filetype' is set, trigger the FileType autocommand
+ // Skip this when called from a modeline and the filetype was
+ // already set to this value.
+ if (!(opt_flags & OPT_MODELINE) || value_changed) {
+ static int ft_recursive = 0;
+ int secure_save = secure;
+
+ // Reset the secure flag, since the value of 'filetype' has
+ // been checked to be safe.
+ secure = 0;
+
+ ft_recursive++;
+ did_filetype = true;
+ // Only pass true for "force" when the value changed or not
+ // used recursively, to avoid endless recurrence.
+ apply_autocmds(EVENT_FILETYPE, buf->b_p_ft, buf->b_fname,
+ value_changed || ft_recursive == 1, buf);
+ ft_recursive--;
+ // Just in case the old "buf" is now invalid
+ if (varp != &(buf->b_p_ft)) {
+ varp = NULL;
+ }
+ secure = secure_save;
+ }
+}
+
+static void do_spelllang_source(win_T *win)
+{
+ char fname[200];
+ char *q = win->w_s->b_p_spl;
+
+ // Skip the first name if it is "cjk".
+ if (strncmp(q, "cjk,", 4) == 0) {
+ q += 4;
+ }
+
+ // Source the spell/LANG.vim in 'runtimepath'.
+ // They could set 'spellcapcheck' depending on the language.
+ // Use the first name in 'spelllang' up to '_region' or
+ // '.encoding'.
+ char *p;
+ for (p = q; *p != NUL; p++) {
+ if (!ASCII_ISALNUM(*p) && *p != '-') {
+ break;
}
}
+ if (p > q) {
+ vim_snprintf(fname, sizeof(fname), "spell/%.*s.vim", (int)(p - q), q);
+ source_runtime(fname, DIP_ALL);
+ }
+}
+
+/// Handle string options that need some action to perform when changed.
+/// The new value must be allocated.
+///
+/// @param opt_idx index in options[] table
+/// @param varp pointer to the option variable
+/// @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
+///
+/// @return NULL for success, or an untranslated error message for an error
+static char *did_set_string_option_for(buf_T *buf, win_T *win, int opt_idx, char **varp,
+ char *oldval, char *errbuf, size_t errbuflen, int opt_flags,
+ int *value_checked)
+{
+ char *errmsg = NULL;
+ bool did_chartab = false;
+ vimoption_T *opt = get_option(opt_idx);
+ bool free_oldval = (opt->flags & P_ALLOCED);
+ bool value_changed = false;
+
+ // Get the global option to compare with, otherwise we would have to check
+ // two values for all local options.
+ char **gvarp = (char **)get_varp_scope(opt, OPT_GLOBAL);
- // If error detected, restore the previous value.
+ // Disallow changing some options from secure mode
+ if ((secure || sandbox != 0) && (opt->flags & P_SECURE)) {
+ errmsg = e_secure;
+ // Check for a "normal" directory or file name in some options.
+ } else if (check_illegal_path_names(*varp, opt->flags)) {
+ errmsg = e_invarg;
+ } else if (gvarp == &p_bkc) { // 'backupcopy'
+ did_set_backupcopy(buf, oldval, opt_flags, &errmsg);
+ } else if (varp == &p_bex // 'backupext'
+ || varp == &p_pm) { // 'patchmode'
+ did_set_backupext_or_patchmode(&errmsg);
+ } else if (varp == &win->w_p_briopt) { // 'breakindentopt'
+ did_set_breakindentopt(win, &errmsg);
+ } else if (varp == &p_isi // 'isident'
+ || varp == &buf->b_p_isk // 'iskeyword'
+ || varp == &p_isp // 'isprint'
+ || varp == &p_isf) { // 'isfname'
+ did_set_isopt(buf, &did_chartab, &errmsg);
+ } else if (varp == &p_hf) { // 'helpfile'
+ did_set_helpfile();
+ } else if (varp == &p_rtp // 'runtimepath'
+ || varp == &p_pp) { // 'packpath'
+ runtime_search_path_invalidate();
+ } else if (gvarp == &win->w_allbuf_opt.wo_culopt) { // 'cursorlineopt'
+ did_set_cursorlineopt(win, varp, &errmsg);
+ } else if (varp == &win->w_p_cc) { // 'colorcolumn'
+ errmsg = check_colorcolumn(win);
+ } else if (varp == &p_hlg) { // 'helplang'
+ did_set_helplang(&errmsg);
+ } else if (varp == &p_hl) { // 'highlight'
+ did_set_highlight(varp, &errmsg);
+ } else if (varp == &p_jop) { // 'jumpoptions'
+ did_set_opt_flags(p_jop, p_jop_values, &jop_flags, true, &errmsg);
+ } else if (gvarp == &p_nf) { // 'nrformats'
+ did_set_opt_strings(*varp, p_nf_values, true, &errmsg);
+ } else if (varp == &p_ssop) { // 'sessionoptions'
+ did_set_sessionoptions(oldval, &errmsg);
+ } else if (varp == &p_vop) { // 'viewoptions'
+ did_set_opt_flags(p_vop, p_ssop_values, &vop_flags, true, &errmsg);
+ } else if (varp == &p_rdb) { // 'redrawdebug'
+ did_set_opt_flags(p_rdb, p_rdb_values, &rdb_flags, true, &errmsg);
+ } else if (varp == &p_sbo) { // 'scrollopt'
+ did_set_opt_strings(p_sbo, p_scbopt_values, true, &errmsg);
+ } else if (varp == &p_ambw // 'ambiwidth'
+ || (int *)varp == &p_emoji) { // 'emoji'
+ did_set_ambiwidth(&errmsg);
+ } else if (varp == &p_bg) { // 'background'
+ did_set_background(&errmsg);
+ } else if (varp == &p_wim) { // 'wildmode'
+ did_set_wildmode(&errmsg);
+ } else if (varp == &p_wop) { // 'wildoptions'
+ did_set_opt_flags(p_wop, p_wop_values, &wop_flags, true, &errmsg);
+ } else if (varp == &p_wak) { // 'winaltkeys'
+ did_set_winaltkeys(&errmsg);
+ } else if (varp == &p_ei) { // 'eventignore'
+ did_set_eventignore(&errmsg);
+ } else if (varp == &p_enc // 'encoding'
+ || gvarp == &p_fenc // 'fileencoding'
+ || gvarp == &p_menc) { // 'makeencoding'
+ did_set_encoding(buf, varp, gvarp, opt_flags, &errmsg);
+ } else if (varp == &buf->b_p_keymap) { // 'keymap'
+ did_set_keymap(buf, varp, opt_flags, value_checked, &errmsg);
+ } else if (gvarp == &p_ff) { // 'fileformat'
+ did_set_fileformat(buf, varp, oldval, opt_flags, &errmsg);
+ } else if (varp == &p_ffs) { // 'fileformats'
+ did_set_opt_strings(p_ffs, p_ff_values, true, &errmsg);
+ } else if (gvarp == &p_mps) { // 'matchpairs'
+ did_set_matchpairs(varp, &errmsg);
+ } else if (gvarp == &p_com) { // 'comments'
+ did_set_comments(varp, errbuf, errbuflen, &errmsg);
+ } else if (varp == &p_lcs // global 'listchars'
+ || varp == &p_fcs) { // global 'fillchars'
+ did_set_global_listfillchars(win, varp, opt_flags, &errmsg);
+ } else if (varp == &win->w_p_lcs) { // local 'listchars'
+ errmsg = set_chars_option(win, varp, true);
+ } else if (varp == &win->w_p_fcs) { // local 'fillchars'
+ errmsg = set_chars_option(win, varp, true);
+ } else if (varp == &p_cedit) { // 'cedit'
+ errmsg = check_cedit();
+ } else if (varp == &p_vfile) { // 'verbosefile'
+ did_set_verbosefile(&errmsg);
+ } else if (varp == &p_shada) { // 'shada'
+ did_set_shada(&opt, &opt_idx, &free_oldval, errbuf, errbuflen, &errmsg);
+ } else if (gvarp == &p_sbr) { // 'showbreak'
+ did_set_showbreak(varp, &errmsg);
+ } else if (varp == &p_guicursor) { // 'guicursor'
+ errmsg = parse_shape_opt(SHAPE_CURSOR);
+ } else if (varp == &p_langmap) { // 'langmap'
+ langmap_set();
+ } else if (varp == &p_breakat) { // 'breakat'
+ fill_breakat_flags();
+ } else if (varp == &p_titlestring // 'titlestring'
+ || varp == &p_iconstring) { // 'iconstring'
+ did_set_titleiconstring(varp);
+ } else if (varp == &p_sel) { // 'selection'
+ did_set_selection(&errmsg);
+ } else if (varp == &p_slm) { // 'selectmode'
+ did_set_opt_strings(p_slm, p_slm_values, true, &errmsg);
+ } else if (varp == &p_km) { // 'keymodel'
+ did_set_keymodel(&errmsg);
+ } else if (varp == &p_mousem) { // 'mousemodel'
+ did_set_opt_strings(p_mousem, p_mousem_values, false, &errmsg);
+ } else if (varp == &p_mousescroll) { // 'mousescroll'
+ errmsg = check_mousescroll(p_mousescroll);
+ } else if (varp == &p_swb) { // 'switchbuf'
+ did_set_opt_flags(p_swb, p_swb_values, &swb_flags, true, &errmsg);
+ } else if (varp == &p_spk) { // 'splitkeep'
+ did_set_opt_strings(p_spk, p_spk_values, false, &errmsg);
+ } else if (varp == &p_debug) { // 'debug'
+ did_set_opt_strings(p_debug, p_debug_values, true, &errmsg);
+ } else if (varp == &p_dy) { // 'display'
+ did_set_display(&errmsg);
+ } else if (varp == &p_ead) { // 'eadirection'
+ did_set_opt_strings(p_ead, p_ead_values, false, &errmsg);
+ } else if (varp == &p_cb) { // 'clipboard'
+ did_set_opt_flags(p_cb, p_cb_values, &cb_flags, true, &errmsg);
+ } else if (varp == &win->w_s->b_p_spf) { // 'spellfile'
+ did_set_spellfile(varp, &errmsg);
+ } else if (varp == &win->w_s->b_p_spl) { // 'spell'
+ did_set_spell(varp, &errmsg);
+ } else if (varp == &win->w_s->b_p_spc) { // 'spellcapcheck'
+ did_set_spellcapcheck(win, &errmsg);
+ } else if (varp == &win->w_s->b_p_spo) { // 'spelloptions'
+ did_set_spelloptions(win, &errmsg);
+ } else if (varp == &p_sps) { // 'spellsuggest'
+ did_set_spellsuggest(&errmsg);
+ } else if (varp == &p_msm) { // 'mkspellmem'
+ did_set_mkspellmem(&errmsg);
+ } else if (gvarp == &p_bh) { // 'bufhidden'
+ did_set_opt_strings(buf->b_p_bh, p_bufhidden_values, false, &errmsg);
+ } else if (gvarp == &p_bt) { // 'buftype'
+ did_set_buftype(buf, win, &errmsg);
+ } else if (gvarp == &p_stl // 'statusline'
+ || gvarp == &p_wbr // 'winbar'
+ || varp == &p_tal // 'tabline'
+ || varp == &p_ruf // 'rulerformat'
+ || varp == &win->w_p_stc) { // 'statuscolumn'
+ did_set_statusline(win, varp, gvarp, &errmsg);
+ } else if (gvarp == &p_cpt) { // 'complete'
+ did_set_complete(varp, errbuf, errbuflen, &errmsg);
+ } else if (varp == &p_cot) { // 'completeopt'
+ did_set_completeopt(&errmsg);
+#ifdef BACKSLASH_IN_FILENAME
+ } else if (gvarp == &p_csl) { // 'completeslash'
+ did_set_completeslash(buf, &errmsg);
+#endif
+ } else if (varp == &win->w_p_scl) { // 'signcolumn'
+ did_set_signcolumn(win, varp, oldval, &errmsg);
+ } else if (varp == &p_sloc) { // 'showcmdloc'
+ did_set_opt_strings(*varp, p_sloc_values, false, &errmsg);
+ } else if (gvarp == &win->w_allbuf_opt.wo_fdc) { // 'foldcolumn'
+ did_set_foldcolumn(varp, &errmsg);
+ } else if (varp == &p_pt) { // 'pastetoggle'
+ did_set_pastetoggle();
+ } else if (varp == &p_bs) { // 'backspace'
+ did_set_backspace(&errmsg);
+ } else if (varp == &p_bo) {
+ did_set_opt_flags(p_bo, p_bo_values, &bo_flags, true, &errmsg);
+ } else if (gvarp == &p_tc) { // 'tagcase'
+ did_set_tagcase(buf, opt_flags, &errmsg);
+ } else if (varp == &p_cmp) { // 'casemap'
+ did_set_opt_flags(p_cmp, p_cmp_values, &cmp_flags, true, &errmsg);
+ } else if (varp == &p_dip) { // 'diffopt'
+ did_set_diffopt(&errmsg);
+ } else if (gvarp == &win->w_allbuf_opt.wo_fdm) { // 'foldmethod'
+ did_set_foldmethod(win, varp, &errmsg);
+ } else if (gvarp == &win->w_allbuf_opt.wo_fmr) { // 'foldmarker'
+ did_set_foldmarker(win, varp, &errmsg);
+ } else if (gvarp == &p_cms) { // 'commentstring'
+ did_set_commentstring(varp, &errmsg);
+ } else if (varp == &p_fdo) { // 'foldopen'
+ did_set_opt_flags(p_fdo, p_fdo_values, &fdo_flags, true, &errmsg);
+ } else if (varp == &p_fcl) { // 'foldclose'
+ did_set_opt_strings(*varp, p_fcl_values, true, &errmsg);
+ } else if (gvarp == &win->w_allbuf_opt.wo_fdi) { // 'foldignore'
+ did_set_foldignore(win);
+ } else if (gvarp == &p_ve) { // 'virtualedit'
+ did_set_virtualedit(win, opt_flags, oldval, &errmsg);
+ } else if (gvarp == &p_cino) { // 'cinoptions'
+ // TODO(vim): recognize errors
+ parse_cino(buf);
+ } else if (gvarp == &p_lop) { // 'lispoptions'
+ did_set_lispoptions(varp, &errmsg);
+ } else if (varp == &p_icm) { // 'inccommand'
+ did_set_opt_strings(*varp, p_icm_values, false, &errmsg);
+ } else if (gvarp == &p_ft // 'filetype'
+ || gvarp == &p_syn) { // 'syntax'
+ did_set_filetype_or_syntax(varp, oldval, value_checked, &value_changed, &errmsg);
+ } else if (varp == &win->w_p_winhl) { // 'winhighlight'
+ did_set_winhl(win, &errmsg);
+ } else if (varp == &p_tpf) {
+ did_set_opt_flags(p_tpf, p_tpf_values, &tpf_flags, true, &errmsg);
+ } else if (varp == &buf->b_p_vsts) { // 'varsofttabstop'
+ did_set_varsoftabstop(buf, varp, &errmsg);
+ } else if (varp == &buf->b_p_vts) { // 'vartabstop'
+ did_set_vartabstop(buf, win, varp, &errmsg);
+ } else if (varp == &p_dex // 'diffexpr'
+ || gvarp == &win->w_allbuf_opt.wo_fde // 'foldexpr'
+ || gvarp == &win->w_allbuf_opt.wo_fdt // 'foldtext'
+ || gvarp == &p_fex // 'formatexpr'
+ || gvarp == &p_inex // 'includeexpr'
+ || gvarp == &p_inde // 'indentexpr'
+ || varp == &p_pex // 'patchexpr'
+ || varp == &p_ccv) { // 'charconvert'
+ did_set_optexpr(varp);
+ if (varp == &win->w_p_fde && foldmethodIsExpr(win)) {
+ foldUpdateAll(win);
+ }
+ } else if (gvarp == &p_cfu) { // 'completefunc'
+ set_completefunc_option(&errmsg);
+ } else if (gvarp == &p_ofu) { // 'omnifunc'
+ set_omnifunc_option(buf, &errmsg);
+ } else if (gvarp == &p_tsrfu) { // 'thesaurusfunc'
+ set_thesaurusfunc_option(&errmsg);
+ } else if (varp == &p_opfunc) { // 'operatorfunc'
+ set_operatorfunc_option(&errmsg);
+ } else if (varp == &p_qftf) { // 'quickfixtextfunc'
+ qf_process_qftf_option(&errmsg);
+ } else if (gvarp == &p_tfu) { // 'tagfunc'
+ set_tagfunc_option(&errmsg);
+ } else if (varp == &p_ww) { // 'whichwrap'
+ did_set_option_listflag(varp, WW_ALL, errbuf, errbuflen, &errmsg);
+ } else if (varp == &p_shm) { // 'shortmess'
+ did_set_option_listflag(varp, SHM_ALL, errbuf, errbuflen, &errmsg);
+ } else if (varp == &p_cpo) { // 'cpoptions'
+ did_set_option_listflag(varp, CPO_VI, errbuf, errbuflen, &errmsg);
+ } else if (varp == &buf->b_p_fo) { // 'formatoptions'
+ did_set_option_listflag(varp, FO_ALL, errbuf, errbuflen, &errmsg);
+ } else if (varp == &win->w_p_cocu) { // 'concealcursor'
+ did_set_option_listflag(varp, COCU_ALL, errbuf, errbuflen, &errmsg);
+ } else if (varp == &p_mouse) { // 'mouse'
+ did_set_option_listflag(varp, MOUSE_ALL, errbuf, errbuflen, &errmsg);
+ } else if (gvarp == &p_flp) { // 'formatlistpat'
+ if (win->w_briopt_list) {
+ // Changing Formatlistpattern when briopt includes the list setting:
+ // redraw
+ redraw_all_later(UPD_NOT_VALID);
+ }
+ }
+
+ // If an error is detected, restore the previous value.
if (errmsg != NULL) {
free_string_option(*varp);
*varp = oldval;
// When resetting some values, need to act on it.
if (did_chartab) {
- (void)init_chartab();
+ (void)buf_init_chartab(buf, true);
}
} else {
// Remember where the option was set.
@@ -1598,7 +1886,7 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
&& (opt->indir & PV_BOTH)) {
// global option with local value set to use global value; free
// the local value and make it empty
- p = get_varp_scope(opt, OPT_LOCAL);
+ char *p = get_varp_scope(opt, OPT_LOCAL);
free_string_option(*(char **)p);
*(char **)p = empty_option;
} else if (!(opt_flags & OPT_LOCAL) && opt_flags != OPT_GLOBAL) {
@@ -1607,65 +1895,12 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
}
// Trigger the autocommand only after setting the flags.
- // When 'syntax' is set, load the syntax of that name
- if (varp == &(curbuf->b_p_syn)) {
- static int syn_recursive = 0;
-
- syn_recursive++;
- // Only pass true for "force" when the value changed or not used
- // recursively, to avoid endless recurrence.
- apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn, curbuf->b_fname,
- value_changed || syn_recursive == 1, curbuf);
- curbuf->b_flags |= BF_SYN_SET;
- syn_recursive--;
- } else if (varp == &(curbuf->b_p_ft)) {
- // 'filetype' is set, trigger the FileType autocommand
- // Skip this when called from a modeline and the filetype was
- // already set to this value.
- if (!(opt_flags & OPT_MODELINE) || value_changed) {
- static int ft_recursive = 0;
- int secure_save = secure;
-
- // Reset the secure flag, since the value of 'filetype' has
- // been checked to be safe.
- secure = 0;
-
- ft_recursive++;
- did_filetype = true;
- // Only pass true for "force" when the value changed or not
- // used recursively, to avoid endless recurrence.
- apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, curbuf->b_fname,
- value_changed || ft_recursive == 1, curbuf);
- ft_recursive--;
- // Just in case the old "curbuf" is now invalid
- if (varp != &(curbuf->b_p_ft)) {
- varp = NULL;
- }
- secure = secure_save;
- }
- }
- if (varp == &(curwin->w_s->b_p_spl)) {
- char fname[200];
- char *q = curwin->w_s->b_p_spl;
-
- // Skip the first name if it is "cjk".
- if (strncmp(q, "cjk,", 4) == 0) {
- q += 4;
- }
-
- // Source the spell/LANG.vim in 'runtimepath'.
- // They could set 'spellcapcheck' depending on the language.
- // Use the first name in 'spelllang' up to '_region' or
- // '.encoding'.
- for (p = q; *p != NUL; p++) {
- if (!ASCII_ISALNUM(*p) && *p != '-') {
- break;
- }
- }
- if (p > q) {
- vim_snprintf(fname, sizeof(fname), "spell/%.*s.vim", (int)(p - q), q);
- source_runtime(fname, DIP_ALL);
- }
+ if (varp == &buf->b_p_syn) {
+ do_syntax_autocmd(buf, value_changed);
+ } else if (varp == &buf->b_p_ft) {
+ do_filetype_autocmd(buf, varp, opt_flags, value_changed);
+ } else if (varp == &win->w_s->b_p_spl) {
+ do_spelllang_source(win);
}
}
@@ -1673,22 +1908,23 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
setmouse(); // in case 'mouse' changed
}
- // Changing Formatlistpattern when briopt includes the list setting:
- // redraw
- if ((varp == &p_flp || varp == &(curbuf->b_p_flp)) && curwin->w_briopt_list) {
- redraw_all_later(UPD_NOT_VALID);
- }
-
- if (curwin->w_curswant != MAXCOL
+ if (win->w_curswant != MAXCOL
&& (opt->flags & (P_CURSWANT | P_RALL)) != 0) {
- curwin->w_set_curswant = true;
+ win->w_set_curswant = true;
}
- check_redraw(opt->flags);
+ check_redraw_for(buf, win, opt->flags);
return errmsg;
}
+char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf, size_t errbuflen,
+ int opt_flags, int *value_checked)
+{
+ return did_set_string_option_for(curbuf, curwin, opt_idx, varp, oldval, errbuf, errbuflen,
+ opt_flags, value_checked);
+}
+
/// Check an option that can be a range of string values.
///
/// @param list when true: accept a list of values
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index e1db7a8ef7..0611de14aa 100644
--- a/src/nvim/os/env.c
+++ b/src/nvim/os/env.c
@@ -543,7 +543,7 @@ void free_homedir(void)
/// @see {expand_env}
char *expand_env_save(char *src)
{
- return (char *)expand_env_save_opt(src, false);
+ return expand_env_save_opt(src, false);
}
/// Similar to expand_env_save() but when "one" is `true` handle the string as
@@ -551,10 +551,10 @@ char *expand_env_save(char *src)
/// @param src String containing environment variables to expand
/// @param one Should treat as only one file name
/// @see {expand_env}
-char_u *expand_env_save_opt(char *src, bool one)
+char *expand_env_save_opt(char *src, bool one)
{
- char_u *p = xmalloc(MAXPATHL);
- expand_env_esc(src, (char *)p, MAXPATHL, false, one, NULL);
+ char *p = xmalloc(MAXPATHL);
+ expand_env_esc(src, p, MAXPATHL, false, one, NULL);
return p;
}
@@ -656,7 +656,7 @@ void expand_env_esc(char *restrict srcp, char *restrict dst, int dstlen, bool es
#endif
} else if (src[1] == NUL // home directory
|| vim_ispathsep(src[1])
- || vim_strchr(" ,\t\n", src[1]) != NULL) {
+ || vim_strchr(" ,\t\n", (uint8_t)src[1]) != NULL) {
var = homedir;
tail = src + 1;
} else { // user directory
@@ -689,7 +689,7 @@ void expand_env_esc(char *restrict srcp, char *restrict dst, int dstlen, bool es
#else
// cannot expand user's home directory, so don't try
var = NULL;
- tail = (char_u *)""; // for gcc
+ tail = ""; // for gcc
#endif // UNIX
}
@@ -697,7 +697,7 @@ void expand_env_esc(char *restrict srcp, char *restrict dst, int dstlen, bool es
// If 'shellslash' is set change backslashes to forward slashes.
// Can't use slash_adjust(), p_ssl may be set temporarily.
if (p_ssl && var != NULL && vim_strchr(var, '\\') != NULL) {
- char_u *p = xstrdup(var);
+ char *p = xstrdup(var);
if (mustfree) {
xfree(var);
@@ -1198,7 +1198,7 @@ bool os_setenv_append_path(const char *fname)
// No prescribed maximum on unix.
# define MAX_ENVPATHLEN INT_MAX
#endif
- if (!path_is_absolute((char_u *)fname)) {
+ if (!path_is_absolute(fname)) {
internal_error("os_setenv_append_path()");
return false;
}
diff --git a/src/nvim/os/fileio.c b/src/nvim/os/fileio.c
index e93e1febcb..5af39555c9 100644
--- a/src/nvim/os/fileio.c
+++ b/src/nvim/os/fileio.c
@@ -16,6 +16,8 @@
#include "auto/config.h"
#include "nvim/gettext.h"
+#include "nvim/globals.h"
+#include "nvim/log.h"
#include "nvim/macros.h"
#include "nvim/memory.h"
#include "nvim/message.h"
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index e0449d468a..6157341ec9 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -146,11 +146,7 @@ bool os_isdir(const char *name)
return false;
}
- if (!S_ISDIR(mode)) {
- return false;
- }
-
- return true;
+ return S_ISDIR(mode);
}
/// Check what `name` is:
@@ -302,7 +298,9 @@ static bool is_executable(const char *name, char **abspath)
static bool is_executable_ext(const char *name, char **abspath)
FUNC_ATTR_NONNULL_ARG(1)
{
- const bool is_unix_shell = strstr((char *)path_tail(p_sh), "sh") != NULL;
+ const bool is_unix_shell = strstr(path_tail(p_sh), "powershell") == NULL
+ && strstr(path_tail(p_sh), "pwsh") == NULL
+ && strstr(path_tail(p_sh), "sh") != NULL;
char *nameext = strrchr(name, '.');
size_t nameext_len = nameext ? strlen(nameext) : 0;
xstrlcpy(os_buf, name, sizeof(os_buf));
@@ -328,11 +326,11 @@ static bool is_executable_ext(const char *name, char **abspath)
const char *ext_end = ext;
size_t ext_len =
- copy_option_part(&ext_end, (char_u *)buf_end,
+ copy_option_part((char **)&ext_end, buf_end,
sizeof(os_buf) - (size_t)(buf_end - os_buf), ENV_SEPSTR);
if (ext_len != 0) {
bool in_pathext = nameext_len == ext_len
- && 0 == mb_strnicmp((char_u *)nameext, (char_u *)ext, ext_len);
+ && 0 == mb_strnicmp(nameext, ext, ext_len);
if (((in_pathext || is_unix_shell) && is_executable(name, abspath))
|| is_executable(os_buf, abspath)) {
@@ -789,14 +787,14 @@ int os_setperm(const char *const name, int perm)
// Return a pointer to the ACL of file "fname" in allocated memory.
// Return NULL if the ACL is not available for whatever reason.
-vim_acl_T os_get_acl(const char_u *fname)
+vim_acl_T os_get_acl(const char *fname)
{
vim_acl_T ret = NULL;
return ret;
}
// Set the ACL of file "fname" to "acl" (unless it's NULL).
-void os_set_acl(const char_u *fname, vim_acl_T aclent)
+void os_set_acl(const char *fname, vim_acl_T aclent)
{
if (aclent == NULL) {
return;
@@ -912,12 +910,11 @@ int os_file_is_writable(const char *name)
/// Rename a file or directory.
///
/// @return `OK` for success, `FAIL` for failure.
-int os_rename(const char_u *path, const char_u *new_path)
+int os_rename(const char *path, const char *new_path)
FUNC_ATTR_NONNULL_ALL
{
int r;
- RUN_UV_FS_FUNC(r, uv_fs_rename, (const char *)path, (const char *)new_path,
- NULL);
+ RUN_UV_FS_FUNC(r, uv_fs_rename, path, new_path, NULL);
return (r == kLibuvSuccess ? OK : FAIL);
}
@@ -1380,7 +1377,7 @@ bool os_is_reparse_point_include(const char *path)
}
p = utf16_path;
- if (isalpha(p[0]) && p[1] == L':' && IS_PATH_SEP(p[2])) {
+ if (isalpha((uint8_t)p[0]) && p[1] == L':' && IS_PATH_SEP(p[2])) {
p += 3;
} else if (IS_PATH_SEP(p[0]) && IS_PATH_SEP(p[1])) {
p += 2;
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index 5d2ac1e102..759b3cf83c 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -44,7 +44,6 @@ typedef enum {
static Stream read_stream = { .closed = true }; // Input before UI starts.
static RBuffer *input_buffer = NULL;
static bool input_eof = false;
-static int global_fd = -1;
static bool blocking = false;
static int cursorhold_time = 0; ///< time waiting for CursorHold event
static int cursorhold_tb_change_cnt = 0; ///< tb_change_cnt when waiting started
@@ -58,25 +57,14 @@ void input_init(void)
input_buffer = rbuffer_new(INPUT_BUFFER_SIZE + MAX_KEY_CODE_LEN);
}
-void input_global_fd_init(int fd)
-{
- global_fd = fd;
-}
-
-/// Global TTY (or pipe for "-es") input stream, before UI starts.
-int input_global_fd(void)
-{
- return global_fd;
-}
-
-void input_start(int fd)
+void input_start(void)
{
if (!read_stream.closed) {
return;
}
- input_global_fd_init(fd);
- rstream_init_fd(&main_loop, &read_stream, fd, READ_BUFFER_SIZE);
+ used_stdin = true;
+ rstream_init_fd(&main_loop, &read_stream, STDIN_FILENO, READ_BUFFER_SIZE);
rstream_start(&read_stream, input_read_cb, NULL);
}
@@ -266,7 +254,8 @@ size_t input_enqueue(String keys)
uint8_t buf[19] = { 0 };
// Do not simplify the keys here. Simplification will be done later.
unsigned int new_size
- = trans_special((const char **)&ptr, (size_t)(end - ptr), buf, FSK_KEYCODE, true, NULL);
+ = trans_special((const char **)&ptr, (size_t)(end - ptr), (char *)buf, FSK_KEYCODE, true,
+ NULL);
if (new_size) {
new_size = handle_mouse_event(&ptr, buf, new_size);
diff --git a/src/nvim/os/input.h b/src/nvim/os/input.h
index 7026781407..6f25efdc7b 100644
--- a/src/nvim/os/input.h
+++ b/src/nvim/os/input.h
@@ -7,6 +7,8 @@
#include "nvim/api/private/defs.h"
#include "nvim/event/multiqueue.h"
+EXTERN bool used_stdin INIT(= false);
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/input.h.generated.h"
#endif
diff --git a/src/nvim/os/nvim.manifest b/src/nvim/os/nvim.manifest
new file mode 100644
index 0000000000..8878822a5d
--- /dev/null
+++ b/src/nvim/os/nvim.manifest
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
+ <assemblyIdentity
+ processorArchitecture="*"
+ version="0.9.0.0"
+ type="win32"
+ name="Neovim"
+ />
+ <description>Neovim</description>
+ <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <application>
+ <!-- Windows 10 and Windows 11 -->
+ <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+ <!-- Windows 8.1 -->
+ <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+ <!-- Windows 8 -->
+ <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+ </application>
+ </compatibility>
+</assembly>
diff --git a/src/nvim/os/os_win_console.c b/src/nvim/os/os_win_console.c
index ec0f03a1dc..006e27d28f 100644
--- a/src/nvim/os/os_win_console.c
+++ b/src/nvim/os/os_win_console.c
@@ -10,11 +10,12 @@
# include "os/os_win_console.c.generated.h"
#endif
+static char origTitle[256] = { 0 };
static HWND hWnd = NULL;
static HICON hOrigIconSmall = NULL;
static HICON hOrigIcon = NULL;
-int os_get_conin_fd(void)
+int os_open_conin_fd(void)
{
const HANDLE conin_handle = CreateFile("CONIN$",
GENERIC_READ | GENERIC_WRITE,
@@ -30,7 +31,7 @@ int os_get_conin_fd(void)
void os_replace_stdin_to_conin(void)
{
close(STDIN_FILENO);
- const int conin_fd = os_get_conin_fd();
+ const int conin_fd = os_open_conin_fd();
assert(conin_fd == STDIN_FILENO);
}
@@ -92,3 +93,15 @@ void os_icon_init(void)
}
}
}
+
+/// Saves the original Windows console title.
+void os_title_save(void)
+{
+ GetConsoleTitle(origTitle, sizeof(origTitle));
+}
+
+/// Resets the original Windows console title.
+void os_title_reset(void)
+{
+ SetConsoleTitle(origTitle);
+}
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index 8177f06c64..f1e2c5440f 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -221,7 +221,7 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
// "command" below.
len++; // add space
for (j = 0; pat[i][j] != NUL; j++) {
- if (vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL) {
+ if (vim_strchr(SHELL_SPECIAL, (uint8_t)pat[i][j]) != NULL) {
len++; // may add a backslash
}
len++;
@@ -304,14 +304,14 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
// backslash inside backticks, before a special character
// and before a backtick.
if (intick
- || vim_strchr(SHELL_SPECIAL, pat[i][j + 1]) != NULL
+ || vim_strchr(SHELL_SPECIAL, (uint8_t)pat[i][j + 1]) != NULL
|| pat[i][j + 1] == '`') {
*p++ = '\\';
}
j++;
} else if (!intick
&& ((flags & EW_KEEPDOLLAR) == 0 || pat[i][j] != '$')
- && vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL) {
+ && vim_strchr(SHELL_SPECIAL, (uint8_t)pat[i][j]) != NULL) {
// Put a backslash before a special character, but not
// when inside ``. And not for $var when EW_KEEPDOLLAR is
// set.
@@ -570,7 +570,7 @@ notfound:
char **shell_build_argv(const char *cmd, const char *extra_args)
FUNC_ATTR_NONNULL_RET
{
- size_t argc = tokenize(p_sh, NULL) + (cmd ? tokenize((char *)p_shcf, NULL) : 0);
+ size_t argc = tokenize(p_sh, NULL) + (cmd ? tokenize(p_shcf, NULL) : 0);
char **rv = xmalloc((argc + 4) * sizeof(*rv));
// Split 'shell'
@@ -581,7 +581,7 @@ char **shell_build_argv(const char *cmd, const char *extra_args)
}
if (cmd) {
- i += tokenize((char *)p_shcf, rv + i); // Split 'shellcmdflag'
+ i += tokenize(p_shcf, rv + i); // Split 'shellcmdflag'
rv[i++] = shell_xescape_xquote(cmd); // Copy (and escape) `cmd`.
}
@@ -1332,7 +1332,7 @@ static char *shell_xescape_xquote(const char *cmd)
const char *ecmd = cmd;
if (*p_sxe != NUL && strcmp(p_sxq, "(") == 0) {
- ecmd = vim_strsave_escaped_ext(cmd, (char *)p_sxe, '^', false);
+ ecmd = vim_strsave_escaped_ext(cmd, p_sxe, '^', false);
}
size_t ncmd_size = strlen(ecmd) + strlen(p_sxq) * 2 + 1;
char *ncmd = xmalloc(ncmd_size);
diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c
index a99a8d25ce..6b07b6ef70 100644
--- a/src/nvim/os/stdpaths.c
+++ b/src/nvim/os/stdpaths.c
@@ -121,7 +121,7 @@ char *get_xdg_home(const XDGVarType idx)
#endif
#ifdef BACKSLASH_IN_FILENAME
- slash_adjust((char_u *)dir);
+ slash_adjust(dir);
#endif
}
return dir;
diff --git a/src/nvim/path.c b/src/nvim/path.c
index 9350335e54..e4c2253357 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -6,6 +6,7 @@
#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -154,7 +155,7 @@ char *path_tail_with_sep(char *fname)
/// @post if `len` is not null, stores the length of the executable name.
///
/// @return The position of the last path separator + 1.
-const char_u *invocation_path_tail(const char *invocation, size_t *len)
+const char *invocation_path_tail(const char *invocation, size_t *len)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ARG(1)
{
const char *tail = get_past_head(invocation);
@@ -171,7 +172,7 @@ const char_u *invocation_path_tail(const char *invocation, size_t *len)
*len = (size_t)(p - tail);
}
- return (char_u *)tail;
+ return tail;
}
/// Get the next path component of a path name.
@@ -210,10 +211,10 @@ int path_head_length(void)
/// @return
/// - True if path begins with a path head
/// - False otherwise
-bool is_path_head(const char_u *path)
+bool is_path_head(const char *path)
{
#ifdef MSWIN
- return isalpha(path[0]) && path[1] == ':';
+ return isalpha((uint8_t)path[0]) && path[1] == ':';
#else
return vim_ispathsep(*path);
#endif
@@ -228,7 +229,7 @@ char *get_past_head(const char *path)
#ifdef MSWIN
// May skip "c:"
- if (is_path_head((char_u *)path)) {
+ if (is_path_head(path)) {
retval = path + 2;
}
#endif
@@ -510,7 +511,7 @@ char *FullName_save(const char *fname, bool force)
char *save_abs_path(const char *name)
FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
{
- if (!path_is_absolute((char_u *)name)) {
+ if (!path_is_absolute(name)) {
return FullName_save(name, true);
}
return xstrdup(name);
@@ -535,7 +536,7 @@ bool path_has_wildcard(const char *p)
// Windows:
const char *wildcards = "?*$[`";
#endif
- if (vim_strchr(wildcards, *p) != NULL
+ if (vim_strchr(wildcards, (uint8_t)(*p)) != NULL
|| (p[0] == '~' && p[1] != NUL)) {
return true;
}
@@ -648,7 +649,7 @@ static size_t do_path_expand(garray_T *gap, const char *path, size_t wildoff, in
}
s = p + 1;
} else if (path_end >= path + wildoff
- && (vim_strchr("*?[{~$", *path_end) != NULL
+ && (vim_strchr("*?[{~$", (uint8_t)(*path_end)) != NULL
#ifndef MSWIN
|| (!p_fic && (flags & EW_ICASE) && mb_isalpha(utf_ptr2char((char *)path_end)))
#endif
@@ -782,8 +783,8 @@ static size_t do_path_expand(garray_T *gap, const char *path, size_t wildoff, in
// slow, thus skip it.
size_t matches = (size_t)(gap->ga_len - start_len);
if (matches > 0 && !got_int) {
- qsort(((char_u **)gap->ga_data) + start_len, matches,
- sizeof(char_u *), pstrcmp);
+ qsort(((char **)gap->ga_data) + start_len, matches,
+ sizeof(char *), pstrcmp);
}
return matches;
}
@@ -841,11 +842,11 @@ static bool is_unique(char *maybe_unique, garray_T *gap, int i)
// expanding each into their equivalent path(s).
static void expand_path_option(char *curdir, garray_T *gap)
{
- char_u *path_option = *curbuf->b_p_path == NUL ? p_path : (char_u *)curbuf->b_p_path;
+ char *path_option = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path;
char *buf = xmalloc(MAXPATHL);
while (*path_option != NUL) {
- copy_option_part((char **)&path_option, buf, MAXPATHL, " ,");
+ copy_option_part(&path_option, buf, MAXPATHL, " ,");
if (buf[0] == '.' && (buf[1] == NUL || vim_ispathsep(buf[1]))) {
// Relative to current buffer:
@@ -870,7 +871,7 @@ static void expand_path_option(char *curdir, garray_T *gap)
STRCPY(buf, curdir); // relative to current directory
} else if (path_with_url(buf)) {
continue; // URL can't be used here
- } else if (!path_is_absolute((char_u *)buf)) {
+ } else if (!path_is_absolute(buf)) {
// Expand relative path to their full path equivalent
size_t len = strlen(curdir);
if (len + strlen(buf) + 3 > MAXPATHL) {
@@ -894,11 +895,11 @@ static void expand_path_option(char *curdir, garray_T *gap)
// path: /foo/bar/baz
// fname: /foo/bar/baz/quux.txt
// returns: ^this
-static char_u *get_path_cutoff(char_u *fname, garray_T *gap)
+static char *get_path_cutoff(char *fname, garray_T *gap)
{
int maxlen = 0;
- char_u **path_part = (char_u **)gap->ga_data;
- char_u *cutoff = NULL;
+ char **path_part = gap->ga_data;
+ char *cutoff = NULL;
for (int i = 0; i < gap->ga_len; i++) {
int j = 0;
@@ -984,7 +985,7 @@ static void uniquefy_paths(garray_T *gap, char *pattern)
}
// Shorten the filename while maintaining its uniqueness
- path_cutoff = (char *)get_path_cutoff((char_u *)path, &path_ga);
+ path_cutoff = get_path_cutoff(path, &path_ga);
// Don't assume all files can be reached without path when search
// pattern starts with **/, so only remove path_cutoff
@@ -1011,7 +1012,7 @@ static void uniquefy_paths(garray_T *gap, char *pattern)
}
}
- if (path_is_absolute((char_u *)path)) {
+ if (path_is_absolute(path)) {
// Last resort: shorten relative to curdir if possible.
// 'possible' means:
// 1. It is under the current directory.
@@ -1127,7 +1128,7 @@ static int expand_in_path(garray_T *const gap, char *const pattern, const int fl
return 0;
}
- char *const paths = (char *)ga_concat_strings(&path_ga);
+ char *const paths = ga_concat_strings(&path_ga);
ga_clear_strings(&path_ga);
int glob_flags = 0;
@@ -1137,7 +1138,7 @@ static int expand_in_path(garray_T *const gap, char *const pattern, const int fl
if (flags & EW_ADDSLASH) {
glob_flags |= WILD_ADD_SLASH;
}
- globpath(paths, pattern, gap, glob_flags);
+ globpath(paths, pattern, gap, glob_flags, false);
xfree(paths);
return gap->ga_len;
@@ -1145,12 +1146,12 @@ static int expand_in_path(garray_T *const gap, char *const pattern, const int fl
/// Return true if "p" contains what looks like an environment variable.
/// Allowing for escaping.
-static bool has_env_var(char_u *p)
+static bool has_env_var(char *p)
{
for (; *p; MB_PTR_ADV(p)) {
if (*p == '\\' && p[1] != NUL) {
p++;
- } else if (vim_strchr("$", *p) != NULL) {
+ } else if (vim_strchr("$", (uint8_t)(*p)) != NULL) {
return true;
}
}
@@ -1161,7 +1162,7 @@ static bool has_env_var(char_u *p)
// Return true if "p" contains a special wildcard character, one that Vim
// cannot expand, requires using a shell.
-static bool has_special_wildchar(char_u *p)
+static bool has_special_wildchar(char *p)
{
for (; *p; MB_PTR_ADV(p)) {
// Disallow line break characters.
@@ -1171,13 +1172,13 @@ static bool has_special_wildchar(char_u *p)
// Allow for escaping.
if (*p == '\\' && p[1] != NUL && p[1] != '\r' && p[1] != '\n') {
p++;
- } else if (vim_strchr(SPECIAL_WILDCHAR, *p) != NULL) {
+ } else if (vim_strchr(SPECIAL_WILDCHAR, (uint8_t)(*p)) != NULL) {
// A { must be followed by a matching }.
- if (*p == '{' && vim_strchr((char *)p, '}') == NULL) {
+ if (*p == '{' && vim_strchr(p, '}') == NULL) {
continue;
}
// A quote and backtick must be followed by another one.
- if ((*p == '`' || *p == '\'') && vim_strchr((char *)p, *p) == NULL) {
+ if ((*p == '`' || *p == '\'') && vim_strchr(p, (uint8_t)(*p)) == NULL) {
continue;
}
return true;
@@ -1231,7 +1232,7 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
// avoids starting the shell for each argument separately.
// For `=expr` do use the internal function.
for (int i = 0; i < num_pat; i++) {
- if (has_special_wildchar((char_u *)pat[i])
+ if (has_special_wildchar(pat[i])
&& !(vim_backtick(pat[i]) && pat[i][1] == '=')) {
return os_expand_wildcards(num_pat, pat, num_file, file, flags);
}
@@ -1258,8 +1259,8 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
}
} else {
// First expand environment variables, "~/" and "~user/".
- if ((has_env_var((char_u *)p) && !(flags & EW_NOTENV)) || *p == '~') {
- p = (char *)expand_env_save_opt(p, true);
+ if ((has_env_var(p) && !(flags & EW_NOTENV)) || *p == '~') {
+ p = expand_env_save_opt(p, true);
if (p == NULL) {
p = pat[i];
} else {
@@ -1267,7 +1268,7 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
// On Unix, if expand_env() can't expand an environment
// variable, use the shell to do that. Discard previously
// found file names and start all over again.
- if (has_env_var((char_u *)p) || *p == '~') {
+ if (has_env_var(p) || *p == '~') {
xfree(p);
ga_clear_strings(&ga);
i = os_expand_wildcards(num_pat, pat, num_file, file,
@@ -1286,7 +1287,7 @@ int gen_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, i
// given.
if (path_has_exp_wildcard(p) || (flags & EW_ICASE)) {
if ((flags & EW_PATH)
- && !path_is_absolute((char_u *)p)
+ && !path_is_absolute(p)
&& !(p[0] == '.'
&& (vim_ispathsep(p[1])
|| (p[1] == '.'
@@ -1413,9 +1414,9 @@ static int expand_backtick(garray_T *gap, char *pat, int flags)
/// backslash twice.
/// When 'shellslash' set do it the other way around.
/// When the path looks like a URL leave it unmodified.
-void slash_adjust(char_u *p)
+void slash_adjust(char *p)
{
- if (path_with_url((const char *)p)) {
+ if (path_with_url(p)) {
return;
}
@@ -1428,8 +1429,8 @@ void slash_adjust(char_u *p)
}
while (*p) {
- if (*p == (char_u)psepcN) {
- *p = (char_u)psepc;
+ if (*p == psepcN) {
+ *p = psepc;
}
MB_PTR_ADV(p);
}
@@ -1460,7 +1461,7 @@ void addfile(garray_T *gap, char *f, int flags)
#ifdef FNAME_ILLEGAL
// if the file/dir contains illegal characters, don't add it
- if (strpbrk((char *)f, FNAME_ILLEGAL) != NULL) {
+ if (strpbrk(f, FNAME_ILLEGAL) != NULL) {
return;
}
#endif
@@ -1477,7 +1478,7 @@ void addfile(garray_T *gap, char *f, int flags)
return;
}
- char_u *p = xmalloc(strlen(f) + 1 + isdir);
+ char *p = xmalloc(strlen(f) + 1 + isdir);
STRCPY(p, f);
#ifdef BACKSLASH_IN_FILENAME
@@ -1485,9 +1486,9 @@ void addfile(garray_T *gap, char *f, int flags)
#endif
// Append a slash or backslash after directory names if none is present.
if (isdir && (flags & EW_ADDSLASH)) {
- add_pathsep((char *)p);
+ add_pathsep(p);
}
- GA_APPEND(char_u *, gap, p);
+ GA_APPEND(char *, gap, p);
}
// Converts a file name into a canonical form. It simplifies a file name into
@@ -1689,8 +1690,8 @@ char *find_file_name_in_path(char *ptr, size_t len, int options, long count, cha
}
if (options & FNAME_EXP) {
- file_name = (char *)find_file_in_path(ptr, len, options & ~FNAME_MESS, true,
- rel_fname);
+ file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS, true,
+ rel_fname);
// If the file could not be found in a normal way, try applying
// 'includeexpr' (unless done already).
@@ -1700,8 +1701,8 @@ char *find_file_name_in_path(char *ptr, size_t len, int options, long count, cha
if (tofree != NULL) {
ptr = tofree;
len = strlen(ptr);
- file_name = (char *)find_file_in_path(ptr, len, options & ~FNAME_MESS,
- true, rel_fname);
+ file_name = find_file_in_path(ptr, len, options & ~FNAME_MESS,
+ true, rel_fname);
}
}
if (file_name == NULL && (options & FNAME_MESS)) {
@@ -1716,7 +1717,7 @@ char *find_file_name_in_path(char *ptr, size_t len, int options, long count, cha
while (file_name != NULL && --count > 0) {
xfree(file_name);
file_name =
- (char *)find_file_in_path(ptr, len, options, false, rel_fname);
+ find_file_in_path(ptr, len, options, false, rel_fname);
}
} else {
file_name = xstrnsave(ptr, len);
@@ -1767,7 +1768,7 @@ int path_with_url(const char *fname)
// non-URL text.
// first character must be alpha
- if (!isalpha(*fname)) {
+ if (!ASCII_ISALPHA(*fname)) {
return 0;
}
@@ -1776,7 +1777,7 @@ int path_with_url(const char *fname)
}
// check body: alpha or dash
- for (p = fname + 1; (isalpha(*p) || (*p == '-')); p++) {}
+ for (p = fname + 1; (ASCII_ISALPHA(*p) || (*p == '-')); p++) {}
// check last char is not a dash
if (p[-1] == '-') {
@@ -1799,7 +1800,7 @@ bool path_with_extension(const char *path, const char *extension)
/// Return true if "name" is a full (absolute) path name or URL.
bool vim_isAbsName(char *name)
{
- return path_with_url(name) != 0 || path_is_absolute((char_u *)name);
+ return path_with_url(name) != 0 || path_is_absolute(name);
}
/// Save absolute file name to "buf[len]".
@@ -1823,7 +1824,7 @@ int vim_FullName(const char *fname, char *buf, size_t len, bool force)
if (strlen(fname) > (len - 1)) {
xstrlcpy(buf, fname, len); // truncate
#ifdef MSWIN
- slash_adjust((char_u *)buf);
+ slash_adjust(buf);
#endif
return FAIL;
}
@@ -1838,7 +1839,7 @@ int vim_FullName(const char *fname, char *buf, size_t len, bool force)
xstrlcpy(buf, fname, len); // something failed; use the filename
}
#ifdef MSWIN
- slash_adjust((char_u *)buf);
+ slash_adjust(buf);
#endif
return rv;
}
@@ -1858,7 +1859,7 @@ char *fix_fname(const char *fname)
#ifdef UNIX
return FullName_save(fname, true);
#else
- if (!vim_isAbsName((char_u *)fname)
+ if (!vim_isAbsName((char *)fname)
|| strstr(fname, "..") != NULL
|| strstr(fname, "//") != NULL
# ifdef BACKSLASH_IN_FILENAME
@@ -2075,7 +2076,7 @@ char *path_shorten_fname(char *full_path, char *dir_name)
size_t len = strlen(dir_name);
// If dir_name is a path head, full_path can always be made relative.
- if (len == (size_t)path_head_length() && is_path_head((char_u *)dir_name)) {
+ if (len == (size_t)path_head_length() && is_path_head(dir_name)) {
return full_path + len;
}
@@ -2123,9 +2124,9 @@ int expand_wildcards_eval(char **pat, int *num_file, char ***file, int flags)
if (is_cur_alt_file || *exp_pat == '<') {
emsg_off++;
- eval_pat = (char *)eval_vars((char_u *)exp_pat, (char_u *)exp_pat, &usedlen, NULL, &ignored_msg,
- NULL,
- true);
+ eval_pat = eval_vars(exp_pat, exp_pat, &usedlen, NULL, &ignored_msg,
+ NULL,
+ true);
emsg_off--;
if (eval_pat != NULL) {
star_follows = strcmp(exp_pat + usedlen, "*") == 0;
@@ -2185,15 +2186,15 @@ int expand_wildcards(int num_pat, char **pat, int *num_files, char ***files, int
// Remove names that match 'wildignore'.
if (*p_wig) {
- char_u *ffname;
+ char *ffname;
// check all files in (*files)[]
assert(*num_files == 0 || *files != NULL);
for (i = 0; i < *num_files; i++) {
- ffname = (char_u *)FullName_save((*files)[i], false);
+ ffname = FullName_save((*files)[i], false);
assert((*files)[i] != NULL);
assert(ffname != NULL);
- if (match_file_list((char_u *)p_wig, (char_u *)(*files)[i], ffname)) {
+ if (match_file_list(p_wig, (*files)[i], ffname)) {
// remove this matching file from the list
xfree((*files)[i]);
for (j = i; j + 1 < *num_files; j++) {
@@ -2240,7 +2241,7 @@ int match_suffix(char *fname)
size_t fnamelen = strlen(fname);
size_t setsuflen = 0;
- for (char *setsuf = (char *)p_su; *setsuf;) {
+ for (char *setsuf = p_su; *setsuf;) {
setsuflen = copy_option_part(&setsuf, suf_buf, MAXSUFLEN, ".,");
if (setsuflen == 0) {
char *tail = path_tail(fname);
@@ -2290,7 +2291,7 @@ int path_full_dir_name(char *directory, char *buffer, size_t len)
// Path does not exist (yet). For a full path fail,
// will use the path as-is. For a relative path use
// the current directory and append the file name.
- if (path_is_absolute((const char_u *)directory)) {
+ if (path_is_absolute(directory)) {
// Do not return immediately since we may be in the wrong directory.
retval = FAIL;
} else {
@@ -2360,7 +2361,7 @@ static int path_to_absolute(const char *fname, char *buf, size_t len, int force)
char *end_of_path = (char *)fname;
// expand it if forced or not an absolute path
- if (force || !path_is_absolute((char_u *)fname)) {
+ if (force || !path_is_absolute(fname)) {
p = strrchr(fname, '/');
#ifdef MSWIN
if (p == NULL) {
@@ -2389,14 +2390,14 @@ static int path_to_absolute(const char *fname, char *buf, size_t len, int force)
/// Check if file `fname` is a full (absolute) path.
///
/// @return `true` if "fname" is absolute.
-int path_is_absolute(const char_u *fname)
+int path_is_absolute(const char *fname)
{
#ifdef MSWIN
if (*fname == NUL) {
return false;
}
// A name like "d:/foo" and "//server/share" is absolute
- return ((isalpha(fname[0]) && fname[1] == ':' && vim_ispathsep_nocolon(fname[2]))
+ return ((isalpha((uint8_t)fname[0]) && fname[1] == ':' && vim_ispathsep_nocolon(fname[2]))
|| (vim_ispathsep_nocolon(fname[0]) && fname[0] == fname[1]));
#else
// UNIX: This just checks if the file name starts with '/' or '~'.
@@ -2416,7 +2417,7 @@ void path_guess_exepath(const char *argv0, char *buf, size_t bufsize)
{
const char *path = os_getenv("PATH");
- if (path == NULL || path_is_absolute((char_u *)argv0)) {
+ if (path == NULL || path_is_absolute(argv0)) {
xstrlcpy(buf, argv0, bufsize);
} else if (argv0[0] == '.' || strchr(argv0, PATHSEP)) {
// Relative to CWD.
diff --git a/src/nvim/plines.c b/src/nvim/plines.c
index e4d1ddf8d8..5469d94800 100644
--- a/src/nvim/plines.c
+++ b/src/nvim/plines.c
@@ -23,7 +23,6 @@
#include "nvim/option.h"
#include "nvim/plines.h"
#include "nvim/pos.h"
-#include "nvim/types.h"
#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -52,7 +51,7 @@ int plines_win(win_T *wp, linenr_T lnum, bool winheight)
/// @return Number of filler lines above lnum
int win_get_fill(win_T *wp, linenr_T lnum)
{
- int virt_lines = decor_virt_lines(wp, lnum, NULL);
+ int virt_lines = decor_virt_lines(wp, lnum, NULL, kNone);
// be quick when there are no filler lines
if (diffopt_filler()) {
@@ -441,7 +440,7 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
// Set *headp to the size of what we add.
// Do not use 'showbreak' at the NUL after the text.
added = 0;
- char *const sbr = c == NUL ? empty_option : (char *)get_showbreak_value(wp);
+ char *const sbr = c == NUL ? empty_option : get_showbreak_value(wp);
if ((*sbr != NUL || wp->w_p_bri) && wp->w_p_wrap && vcol != 0) {
colnr_T sbrlen = 0;
int numberwidth = win_col_off(wp);
diff --git a/src/nvim/po/tr.po b/src/nvim/po/tr.po
index 7d6af4d2cf..eb7879efc4 100644
--- a/src/nvim/po/tr.po
+++ b/src/nvim/po/tr.po
@@ -5625,9 +5625,6 @@ msgstr "$VIMRUNTIME öntanımlı konumu: \""
msgid "Nvim is open source and freely distributable"
msgstr "Nvim açık kaynaklıdır ve özgürce dağıtılabilir"
-msgid "https://neovim.io/#chat"
-msgstr "https://neovim.io/#chat"
-
msgid "type :help nvim<Enter> if you are new! "
msgstr "eğer yeniyseniz :help nvim<Enter> "
diff --git a/src/nvim/po/uk.po b/src/nvim/po/uk.po
index b521e37177..06f845f113 100644
--- a/src/nvim/po/uk.po
+++ b/src/nvim/po/uk.po
@@ -5550,9 +5550,6 @@ msgstr " заміна для $VIMRUNTIME: \""
msgid "Nvim is open source and freely distributable"
msgstr "Nvim — це відкрита й вільно розповсюджувана програма"
-msgid "https://neovim.io/#chat"
-msgstr "https://neovim.io/#chat"
-
msgid "type :help nvim<Enter> if you are new! "
msgstr ":help nvim<Enter> якщо ви вперше! "
diff --git a/src/nvim/po/zh_CN.UTF-8.po b/src/nvim/po/zh_CN.UTF-8.po
index 0606adcc37..af050823d3 100644
--- a/src/nvim/po/zh_CN.UTF-8.po
+++ b/src/nvim/po/zh_CN.UTF-8.po
@@ -19,7 +19,7 @@ msgstr ""
"Project-Id-Version: Vim(Simplified Chinese)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-11-17 08:00+0800\n"
-"PO-Revision-Date: 2022-11-17 22:29+0800\n"
+"PO-Revision-Date: 2023-01-24 13:00+0800\n"
"Last-Translator: Sizhe Zhao <prc.zhao@outlook.com>\n"
"Language-Team: Simplified Chinese <i18n-translation@lists.linux.net.cn>\n"
"Language: zh_CN\n"
@@ -7248,17 +7248,13 @@ msgstr " $VIMRUNTIME 预设值: \""
msgid "Nvim is open source and freely distributable"
msgstr "Nvim 是可自由分发的开放源代码软件"
-#: ../version.c:2806
-msgid "https://neovim.io/#chat"
-msgstr ""
-
#: ../version.c:2808
msgid "type :help nvim<Enter> if you are new! "
-msgstr ""
+msgstr "输入 :help nvim<Enter> 了解 Neovim! "
#: ../version.c:2809
msgid "type :checkhealth<Enter> to optimize Nvim"
-msgstr ""
+msgstr "输入 :checkhealth<Enter> 优化 Neovim "
#: ../version.c:2810
msgid "type :q<Enter> to exit "
@@ -7266,11 +7262,12 @@ msgstr "输入 :q<Enter> 退出 "
#: ../version.c:2811
msgid "type :help<Enter> for help "
-msgstr ""
+msgstr "输入 :help<Enter> 查看帮助 "
#: ../version.c:2813
-msgid "type :help news<Enter> to see changes in"
-msgstr ""
+#, c-format
+msgid "type :help news<Enter> to see changes in v%s.%s"
+msgstr "输入 :help news<Enter> 查看 v%s.%s 的变化"
#: ../version.c:2816
msgid "Help poor children in Uganda!"
diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c
index 1d55b2ef31..245ce87865 100644
--- a/src/nvim/popupmenu.c
+++ b/src/nvim/popupmenu.c
@@ -218,11 +218,16 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i
// pum above "pum_win_row"
pum_above = true;
- // Leave two lines of context if possible
- if (curwin->w_wrow - curwin->w_cline_row >= 2) {
- context_lines = 2;
+ if (State == MODE_CMDLINE) {
+ // for cmdline pum, no need for context lines
+ context_lines = 0;
} else {
- context_lines = curwin->w_wrow - curwin->w_cline_row;
+ // Leave two lines of context if possible
+ if (curwin->w_wrow - curwin->w_cline_row >= 2) {
+ context_lines = 2;
+ } else {
+ context_lines = curwin->w_wrow - curwin->w_cline_row;
+ }
}
if (pum_win_row >= size + context_lines) {
@@ -241,13 +246,17 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i
// pum below "pum_win_row"
pum_above = false;
- // Leave two lines of context if possible
- validate_cheight();
- if (curwin->w_cline_row + curwin->w_cline_height - curwin->w_wrow >= 3) {
- context_lines = 3;
+ if (State == MODE_CMDLINE) {
+ // for cmdline pum, no need for context lines
+ context_lines = 0;
} else {
- context_lines = curwin->w_cline_row
- + curwin->w_cline_height - curwin->w_wrow;
+ // Leave two lines of context if possible
+ validate_cheight();
+ if (curwin->w_cline_row + curwin->w_cline_height - curwin->w_wrow >= 3) {
+ context_lines = 3;
+ } else {
+ context_lines = curwin->w_cline_row + curwin->w_cline_height - curwin->w_wrow;
+ }
}
pum_row = pum_win_row + context_lines;
@@ -815,7 +824,7 @@ static bool pum_set_selected(int n, int repeat)
// When the preview window was resized we need to
// update the view on the buffer. Only go back to
// the window when needed, otherwise it will always be
- // redraw.
+ // redrawn.
if (resized) {
no_u_sync++;
win_enter(curwin_save, true);
@@ -878,6 +887,7 @@ void pum_check_clear(void)
grid_free(&pum_grid);
}
pum_is_drawn = false;
+ pum_external = false;
}
}
diff --git a/src/nvim/profile.c b/src/nvim/profile.c
index 866834fc71..fd024f2d38 100644
--- a/src/nvim/profile.c
+++ b/src/nvim/profile.c
@@ -299,7 +299,7 @@ void ex_profile(exarg_T *eap)
if (len == 5 && strncmp(eap->arg, "start", 5) == 0 && *e != NUL) {
xfree(profile_fname);
- profile_fname = (char *)expand_env_save_opt(e, true);
+ profile_fname = expand_env_save_opt(e, true);
do_profiling = PROF_YES;
profile_set_wait(profile_zero());
set_vim_var_nr(VV_PROFILING, 1L);
@@ -354,7 +354,6 @@ char *get_profile_name(expand_T *xp, int idx)
switch (pexpand_what) {
case PEXP_SUBCMD:
return pexpand_cmds[idx];
- // case PEXP_FUNC: TODO
default:
return NULL;
}
@@ -373,13 +372,17 @@ void set_context_in_profile_cmd(expand_T *xp, const char *arg)
return;
}
- if (end_subcmd - arg == 5 && strncmp(arg, "start", 5) == 0) {
+ if ((end_subcmd - arg == 5 && strncmp(arg, "start", 5) == 0)
+ || (end_subcmd - arg == 4 && strncmp(arg, "file", 4) == 0)) {
xp->xp_context = EXPAND_FILES;
xp->xp_pattern = skipwhite(end_subcmd);
return;
+ } else if (end_subcmd - arg == 4 && strncmp(arg, "func", 4) == 0) {
+ xp->xp_context = EXPAND_USER_FUNC;
+ xp->xp_pattern = skipwhite(end_subcmd);
+ return;
}
- // TODO(tarruda): expand function names after "func"
xp->xp_context = EXPAND_NOTHING;
}
@@ -700,17 +703,17 @@ void script_prof_save(proftime_T *tm)
/// Count time spent in children after invoking another script or function.
void script_prof_restore(const proftime_T *tm)
{
- scriptitem_T *si;
+ if (!SCRIPT_ID_VALID(current_sctx.sc_sid)) {
+ return;
+ }
- if (current_sctx.sc_sid > 0 && current_sctx.sc_sid <= script_items.ga_len) {
- si = &SCRIPT_ITEM(current_sctx.sc_sid);
- if (si->sn_prof_on && --si->sn_pr_nest == 0) {
- si->sn_pr_child = profile_end(si->sn_pr_child);
- // don't count wait time
- si->sn_pr_child = profile_sub_wait(*tm, si->sn_pr_child);
- si->sn_pr_children = profile_add(si->sn_pr_children, si->sn_pr_child);
- si->sn_prl_children = profile_add(si->sn_prl_children, si->sn_pr_child);
- }
+ scriptitem_T *si = &SCRIPT_ITEM(current_sctx.sc_sid);
+ if (si->sn_prof_on && --si->sn_pr_nest == 0) {
+ si->sn_pr_child = profile_end(si->sn_pr_child);
+ // don't count wait time
+ si->sn_pr_child = profile_sub_wait(*tm, si->sn_pr_child);
+ si->sn_pr_children = profile_add(si->sn_pr_children, si->sn_pr_child);
+ si->sn_prl_children = profile_add(si->sn_prl_children, si->sn_pr_child);
}
}
@@ -784,17 +787,17 @@ static void script_dump_profile(FILE *fd)
/// Dump the profiling info.
void profile_dump(void)
{
- FILE *fd;
+ if (profile_fname == NULL) {
+ return;
+ }
- if (profile_fname != NULL) {
- fd = os_fopen(profile_fname, "w");
- if (fd == NULL) {
- semsg(_(e_notopen), profile_fname);
- } else {
- script_dump_profile(fd);
- func_dump_profile(fd);
- fclose(fd);
- }
+ FILE *fd = os_fopen(profile_fname, "w");
+ if (fd == NULL) {
+ semsg(_(e_notopen), profile_fname);
+ } else {
+ script_dump_profile(fd);
+ func_dump_profile(fd);
+ fclose(fd);
}
}
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index c895ac16f1..5518fdfa51 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -384,9 +384,9 @@ static char *efmpat_to_regpat(const char *efmpat, char *regpat, efm_T *efminfo,
return NULL;
}
if ((idx && idx < FMT_PATTERN_R
- && vim_strchr("DXOPQ", efminfo->prefix) != NULL)
+ && vim_strchr("DXOPQ", (uint8_t)efminfo->prefix) != NULL)
|| (idx == FMT_PATTERN_R
- && vim_strchr("OPQ", efminfo->prefix) == NULL)) {
+ && vim_strchr("OPQ", (uint8_t)efminfo->prefix) == NULL)) {
semsg(_("E373: Unexpected %%%c in format string"), *efmpat);
return NULL;
}
@@ -468,10 +468,10 @@ static char *scanf_fmt_to_regpat(const char **pefmp, const char *efm, int len, c
static const char *efm_analyze_prefix(const char *efmp, efm_T *efminfo)
FUNC_ATTR_NONNULL_ALL
{
- if (vim_strchr("+-", *efmp) != NULL) {
+ if (vim_strchr("+-", (uint8_t)(*efmp)) != NULL) {
efminfo->flags = *efmp++;
}
- if (vim_strchr("DXAEWINCZGOPQ", *efmp) != NULL) {
+ if (vim_strchr("DXAEWINCZGOPQ", (uint8_t)(*efmp)) != NULL) {
efminfo->prefix = *efmp;
} else {
semsg(_("E376: Invalid %%%c in format string prefix"), *efmp);
@@ -510,7 +510,7 @@ static int efm_to_regpat(const char *efm, int len, efm_T *fmt_ptr, char *regpat)
if (ptr == NULL) {
return FAIL;
}
- } else if (vim_strchr("%\\.^$~[", *efmp) != NULL) {
+ } else if (vim_strchr("%\\.^$~[", (uint8_t)(*efmp)) != NULL) {
*ptr++ = *efmp; // regexp magic characters
} else if (*efmp == '#') {
*ptr++ = '*';
@@ -530,7 +530,7 @@ static int efm_to_regpat(const char *efm, int len, efm_T *fmt_ptr, char *regpat)
} else { // copy normal character
if (*efmp == '\\' && efmp + 1 < efm + len) {
efmp++;
- } else if (vim_strchr(".*^$~[", *efmp) != NULL) {
+ } else if (vim_strchr(".*^$~[", (uint8_t)(*efmp)) != NULL) {
*ptr++ = '\\'; // escape regexp atoms
}
if (*efmp) {
@@ -868,7 +868,7 @@ static int qf_get_nextline(qfstate_T *state)
#endif
}
- remove_bom((char_u *)state->linebuf);
+ remove_bom(state->linebuf);
return QF_OK;
}
@@ -925,7 +925,7 @@ restofline:
// match or no match.
fields->valid = true;
for (; fmt_ptr != NULL; fmt_ptr = fmt_ptr->next) {
- idx = (char_u)fmt_ptr->prefix;
+ idx = (uint8_t)fmt_ptr->prefix;
status = qf_parse_get_fields(linebuf, linelen, fmt_ptr, fields,
qfl->qf_multiline, qfl->qf_multiscan,
&tail);
@@ -1190,13 +1190,15 @@ static void qf_store_title(qf_list_T *qfl, const char *title)
{
XFREE_CLEAR(qfl->qf_title);
- if (title != NULL) {
- size_t len = strlen(title) + 1;
- char *p = xmallocz(len);
-
- qfl->qf_title = p;
- xstrlcpy(p, title, len + 1);
+ if (title == NULL) {
+ return;
}
+
+ size_t len = strlen(title) + 1;
+ char *p = xmallocz(len);
+
+ qfl->qf_title = p;
+ xstrlcpy(p, title, len + 1);
}
/// The title of a quickfix/location list is set, by default, to the command
@@ -1483,7 +1485,7 @@ static int qf_parse_match(char *linebuf, size_t linelen, efm_T *fmt_ptr, regmatc
if ((idx == 'C' || idx == 'Z') && !qf_multiline) {
return QF_FAIL;
}
- if (vim_strchr("EWIN", idx) != NULL) {
+ if (vim_strchr("EWIN", (uint8_t)idx) != NULL) {
fields->type = idx;
} else {
fields->type = 0;
@@ -1524,7 +1526,7 @@ static int qf_parse_match(char *linebuf, size_t linelen, efm_T *fmt_ptr, regmatc
static int qf_parse_get_fields(char *linebuf, size_t linelen, efm_T *fmt_ptr, qffields_T *fields,
int qf_multiline, int qf_multiscan, char **tail)
{
- if (qf_multiscan && vim_strchr("OPQ", fmt_ptr->prefix) == NULL) {
+ if (qf_multiscan && vim_strchr("OPQ", (uint8_t)fmt_ptr->prefix) == NULL) {
return QF_FAIL;
}
@@ -1684,14 +1686,16 @@ int qf_stack_get_bufnr(void)
static void wipe_qf_buffer(qf_info_T *qi)
FUNC_ATTR_NONNULL_ALL
{
- if (qi->qf_bufnr != INVALID_QFBUFNR) {
- buf_T *const qfbuf = buflist_findnr(qi->qf_bufnr);
- if (qfbuf != NULL && qfbuf->b_nwindows == 0) {
- // If the quickfix buffer is not loaded in any window, then
- // wipe the buffer.
- close_buffer(NULL, qfbuf, DOBUF_WIPE, false, false);
- qi->qf_bufnr = INVALID_QFBUFNR;
- }
+ if (qi->qf_bufnr == INVALID_QFBUFNR) {
+ return;
+ }
+
+ buf_T *const qfbuf = buflist_findnr(qi->qf_bufnr);
+ if (qfbuf != NULL && qfbuf->b_nwindows == 0) {
+ // If the quickfix buffer is not loaded in any window, then
+ // wipe the buffer.
+ close_buffer(NULL, qfbuf, DOBUF_WIPE, false, false);
+ qi->qf_bufnr = INVALID_QFBUFNR;
}
}
@@ -3168,15 +3172,15 @@ void qf_list(exarg_T *eap)
// Get the attributes for the different quickfix highlight items. Note
// that this depends on syntax items defined in the qf.vim syntax file
- qfFileAttr = syn_name2attr((char_u *)"qfFileName");
+ qfFileAttr = syn_name2attr("qfFileName");
if (qfFileAttr == 0) {
qfFileAttr = HL_ATTR(HLF_D);
}
- qfSepAttr = syn_name2attr((char_u *)"qfSeparator");
+ qfSepAttr = syn_name2attr("qfSeparator");
if (qfSepAttr == 0) {
qfSepAttr = HL_ATTR(HLF_D);
}
- qfLineAttr = syn_name2attr((char_u *)"qfLineNr");
+ qfLineAttr = syn_name2attr("qfLineNr");
if (qfLineAttr == 0) {
qfLineAttr = HL_ATTR(HLF_N);
}
@@ -3850,10 +3854,11 @@ static buf_T *qf_find_buf(qf_info_T *qi)
}
/// Process the 'quickfixtextfunc' option value.
-/// @return OK or FAIL
-int qf_process_qftf_option(void)
+void qf_process_qftf_option(char **errmsg)
{
- return option_set_callback_func(p_qftf, &qftf_cb);
+ if (option_set_callback_func(p_qftf, &qftf_cb) == FAIL) {
+ *errmsg = e_invarg;
+ }
}
/// Update the w:quickfix_title variable in the quickfix/location list window in
@@ -3878,59 +3883,61 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
{
// Check if a buffer for the quickfix list exists. Update it.
buf_T *buf = qf_find_buf(qi);
- if (buf != NULL) {
- linenr_T old_line_count = buf->b_ml.ml_line_count;
- int qf_winid = 0;
-
- win_T *win;
- if (IS_LL_STACK(qi)) {
- if (curwin->w_llist == qi) {
- win = curwin;
- } else {
- // Find the file window (non-quickfix) with this location list
- win = qf_find_win_with_loclist(qi);
- if (win == NULL) {
- // File window is not found. Find the location list window.
- win = qf_find_win(qi);
- }
- if (win == NULL) {
- return;
- }
+ if (buf == NULL) {
+ return;
+ }
+
+ linenr_T old_line_count = buf->b_ml.ml_line_count;
+ int qf_winid = 0;
+
+ win_T *win;
+ if (IS_LL_STACK(qi)) {
+ if (curwin->w_llist == qi) {
+ win = curwin;
+ } else {
+ // Find the file window (non-quickfix) with this location list
+ win = qf_find_win_with_loclist(qi);
+ if (win == NULL) {
+ // File window is not found. Find the location list window.
+ win = qf_find_win(qi);
+ }
+ if (win == NULL) {
+ return;
}
- qf_winid = (int)win->handle;
}
+ qf_winid = (int)win->handle;
+ }
- // autocommands may cause trouble
- incr_quickfix_busy();
-
- aco_save_T aco;
+ // autocommands may cause trouble
+ incr_quickfix_busy();
- if (old_last == NULL) {
- // set curwin/curbuf to buf and save a few things
- aucmd_prepbuf(&aco, buf);
- }
+ aco_save_T aco;
- qf_update_win_titlevar(qi);
+ if (old_last == NULL) {
+ // set curwin/curbuf to buf and save a few things
+ aucmd_prepbuf(&aco, buf);
+ }
- qf_fill_buffer(qf_get_curlist(qi), buf, old_last, qf_winid);
- buf_inc_changedtick(buf);
+ qf_update_win_titlevar(qi);
- if (old_last == NULL) {
- (void)qf_win_pos_update(qi, 0);
+ qf_fill_buffer(qf_get_curlist(qi), buf, old_last, qf_winid);
+ buf_inc_changedtick(buf);
- // restore curwin/curbuf and a few other things
- aucmd_restbuf(&aco);
- }
+ if (old_last == NULL) {
+ (void)qf_win_pos_update(qi, 0);
- // Only redraw when added lines are visible. This avoids flickering when
- // the added lines are not visible.
- if ((win = qf_find_win(qi)) != NULL && old_line_count < win->w_botline) {
- redraw_buf_later(buf, UPD_NOT_VALID);
- }
+ // restore curwin/curbuf and a few other things
+ aucmd_restbuf(&aco);
+ }
- // always called after incr_quickfix_busy()
- decr_quickfix_busy();
+ // Only redraw when added lines are visible. This avoids flickering when
+ // the added lines are not visible.
+ if ((win = qf_find_win(qi)) != NULL && old_line_count < win->w_botline) {
+ redraw_buf_later(buf, UPD_NOT_VALID);
}
+
+ // always called after incr_quickfix_busy()
+ decr_quickfix_busy();
}
// Add an error line to the quickfix buffer.
@@ -3959,11 +3966,11 @@ static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, const qfli
// buffer.
if (first_bufline
&& (errbuf->b_sfname == NULL
- || path_is_absolute((char_u *)errbuf->b_sfname))) {
+ || path_is_absolute(errbuf->b_sfname))) {
if (*dirname == NUL) {
os_dirname(dirname, MAXPATHL);
}
- shorten_buf_fname(errbuf, (char_u *)dirname, false);
+ shorten_buf_fname(errbuf, dirname, false);
}
xstrlcpy(IObuff, errbuf->b_fname, IOSIZE);
}
@@ -3997,7 +4004,7 @@ static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, const qfli
IObuff + len, IOSIZE - len);
}
- if (ml_append_buf(buf, lnum, (char_u *)IObuff,
+ if (ml_append_buf(buf, lnum, IObuff,
(colnr_T)strlen(IObuff) + 1, false) == FAIL) {
return FAIL;
}
@@ -4188,14 +4195,16 @@ static int qf_id2nr(const qf_info_T *const qi, const unsigned qfid)
static int qf_restore_list(qf_info_T *qi, unsigned save_qfid)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
- if (qf_get_curlist(qi)->qf_id != save_qfid) {
- const int curlist = qf_id2nr(qi, save_qfid);
- if (curlist < 0) {
- // list is not present
- return FAIL;
- }
- qi->qf_curlist = curlist;
+ if (qf_get_curlist(qi)->qf_id == save_qfid) {
+ return OK;
+ }
+
+ const int curlist = qf_id2nr(qi, save_qfid);
+ if (curlist < 0) {
+ // list is not present
+ return FAIL;
}
+ qi->qf_curlist = curlist;
return OK;
}
@@ -5040,8 +5049,8 @@ void ex_cfile(exarg_T *eap)
// first error.
// :caddfile adds to an existing quickfix list. If there is no
// quickfix list then a new list is created.
- int res = qf_init(wp, (char *)p_ef, p_efm, (eap->cmdidx != CMD_caddfile
- && eap->cmdidx != CMD_laddfile),
+ int res = qf_init(wp, p_ef, p_efm, (eap->cmdidx != CMD_caddfile
+ && eap->cmdidx != CMD_laddfile),
qf_cmdtitle(*eap->cmdlinep), enc);
if (wp != NULL) {
qi = GET_LOC_LIST(wp);
@@ -5105,7 +5114,7 @@ static void vgr_init_regmatch(regmmatch_T *regmatch, char *s)
emsg(_(e_noprevre));
return;
}
- regmatch->regprog = vim_regcomp((char *)last_search_pat(), RE_MAGIC);
+ regmatch->regprog = vim_regcomp(last_search_pat(), RE_MAGIC);
} else {
regmatch->regprog = vim_regcomp(s, RE_MAGIC);
}
@@ -5230,8 +5239,7 @@ static bool vgr_match_buflines(qf_list_T *qfl, char *fname, buf_T *buf, char *sp
const size_t sz = sizeof(matches) / sizeof(matches[0]);
// Fuzzy string match
- while (fuzzy_match((char_u *)str + col, (char_u *)spat, false, &score, matches,
- (int)sz) > 0) {
+ while (fuzzy_match(str + col, spat, false, &score, matches, (int)sz) > 0) {
// Pass the buffer number so that it gets used even for a
// dummy buffer, unless duplicate_name is set, then the
// buffer will be wiped out below.
@@ -5737,12 +5745,14 @@ static void wipe_dummy_buffer(buf_T *buf, char *dirname_start)
// 'autochdir' option have changed it.
static void unload_dummy_buffer(buf_T *buf, char *dirname_start)
{
- if (curbuf != buf) { // safety check
- close_buffer(NULL, buf, DOBUF_UNLOAD, false, true);
-
- // When autocommands/'autochdir' option changed directory: go back.
- restore_start_dir(dirname_start);
+ if (curbuf == buf) { // safety check
+ return;
}
+
+ close_buffer(NULL, buf, DOBUF_UNLOAD, false, true);
+
+ // When autocommands/'autochdir' option changed directory: go back.
+ restore_start_dir(dirname_start);
}
/// Copy the specified quickfix entry items into a new dict and append the dict
@@ -5867,32 +5877,34 @@ static int qf_get_list_from_lines(dict_T *what, dictitem_T *di, dict_T *retdict)
int status = FAIL;
// Only a List value is supported
- if (di->di_tv.v_type == VAR_LIST && di->di_tv.vval.v_list != NULL) {
- char *errorformat = p_efm;
- dictitem_T *efm_di;
- // If errorformat is supplied then use it, otherwise use the 'efm'
- // option setting
- if ((efm_di = tv_dict_find(what, S_LEN("efm"))) != NULL) {
- if (efm_di->di_tv.v_type != VAR_STRING
- || efm_di->di_tv.vval.v_string == NULL) {
- return FAIL;
- }
- errorformat = efm_di->di_tv.vval.v_string;
- }
-
- list_T *l = tv_list_alloc(kListLenMayKnow);
- qf_info_T *const qi = qf_alloc_stack(QFLT_INTERNAL);
+ if (di->di_tv.v_type != VAR_LIST || di->di_tv.vval.v_list == NULL) {
+ return FAIL;
+ }
- if (qf_init_ext(qi, 0, NULL, NULL, &di->di_tv, errorformat,
- true, (linenr_T)0, (linenr_T)0, NULL, NULL) > 0) {
- (void)get_errorlist(qi, NULL, 0, 0, l);
- qf_free(&qi->qf_lists[0]);
+ char *errorformat = p_efm;
+ dictitem_T *efm_di;
+ // If errorformat is supplied then use it, otherwise use the 'efm'
+ // option setting
+ if ((efm_di = tv_dict_find(what, S_LEN("efm"))) != NULL) {
+ if (efm_di->di_tv.v_type != VAR_STRING
+ || efm_di->di_tv.vval.v_string == NULL) {
+ return FAIL;
}
- xfree(qi);
+ errorformat = efm_di->di_tv.vval.v_string;
+ }
- tv_dict_add_list(retdict, S_LEN("items"), l);
- status = OK;
+ list_T *l = tv_list_alloc(kListLenMayKnow);
+ qf_info_T *const qi = qf_alloc_stack(QFLT_INTERNAL);
+
+ if (qf_init_ext(qi, 0, NULL, NULL, &di->di_tv, errorformat,
+ true, (linenr_T)0, (linenr_T)0, NULL, NULL) > 0) {
+ (void)get_errorlist(qi, NULL, 0, 0, l);
+ qf_free(&qi->qf_lists[0]);
}
+ xfree(qi);
+
+ tv_dict_add_list(retdict, S_LEN("items"), l);
+ status = OK;
return status;
}
@@ -6935,43 +6947,45 @@ void ex_cexpr(exarg_T *eap)
// Evaluate the expression. When the result is a string or a list we can
// use it to fill the errorlist.
typval_T tv;
- if (eval0(eap->arg, &tv, &eap->nextcmd, true) != FAIL) {
- if ((tv.v_type == VAR_STRING && tv.vval.v_string != NULL)
- || tv.v_type == VAR_LIST) {
- incr_quickfix_busy();
- int res = qf_init_ext(qi, qi->qf_curlist, NULL, NULL, &tv, p_efm,
- (eap->cmdidx != CMD_caddexpr
- && eap->cmdidx != CMD_laddexpr),
- (linenr_T)0, (linenr_T)0,
- qf_cmdtitle(*eap->cmdlinep), NULL);
- if (qf_stack_empty(qi)) {
- decr_quickfix_busy();
- goto cleanup;
- }
- if (res >= 0) {
- qf_list_changed(qf_get_curlist(qi));
- }
- // Remember the current quickfix list identifier, so that we can
- // check for autocommands changing the current quickfix list.
- unsigned save_qfid = qf_get_curlist(qi)->qf_id;
- if (au_name != NULL) {
- apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, curbuf->b_fname, true, curbuf);
- }
- // Jump to the first error for a new list and if autocmds didn't
- // free the list.
- if (res > 0
- && (eap->cmdidx == CMD_cexpr || eap->cmdidx == CMD_lexpr)
- && qflist_valid(wp, save_qfid)) {
- // display the first error
- qf_jump_first(qi, save_qfid, eap->forceit);
- }
+ if (eval0(eap->arg, &tv, &eap->nextcmd, true) == FAIL) {
+ return;
+ }
+
+ if ((tv.v_type == VAR_STRING && tv.vval.v_string != NULL)
+ || tv.v_type == VAR_LIST) {
+ incr_quickfix_busy();
+ int res = qf_init_ext(qi, qi->qf_curlist, NULL, NULL, &tv, p_efm,
+ (eap->cmdidx != CMD_caddexpr
+ && eap->cmdidx != CMD_laddexpr),
+ (linenr_T)0, (linenr_T)0,
+ qf_cmdtitle(*eap->cmdlinep), NULL);
+ if (qf_stack_empty(qi)) {
decr_quickfix_busy();
- } else {
- emsg(_("E777: String or List expected"));
+ goto cleanup;
}
-cleanup:
- tv_clear(&tv);
+ if (res >= 0) {
+ qf_list_changed(qf_get_curlist(qi));
+ }
+ // Remember the current quickfix list identifier, so that we can
+ // check for autocommands changing the current quickfix list.
+ unsigned save_qfid = qf_get_curlist(qi)->qf_id;
+ if (au_name != NULL) {
+ apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, curbuf->b_fname, true, curbuf);
+ }
+ // Jump to the first error for a new list and if autocmds didn't
+ // free the list.
+ if (res > 0
+ && (eap->cmdidx == CMD_cexpr || eap->cmdidx == CMD_lexpr)
+ && qflist_valid(wp, save_qfid)) {
+ // display the first error
+ qf_jump_first(qi, save_qfid, eap->forceit);
+ }
+ decr_quickfix_busy();
+ } else {
+ emsg(_("E777: String or List expected"));
}
+cleanup:
+ tv_clear(&tv);
}
// Get the location list for ":lhelpgrep"
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index e396e54ced..122f3e2020 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -87,7 +87,7 @@ static int toggle_Magic(int x)
#define REGMAGIC 0234
// Utility definitions.
-#define UCHARAT(p) ((int)(*(char_u *)(p)))
+#define UCHARAT(p) ((int)(*(uint8_t *)(p)))
// Used for an error (down from) vim_regcomp(): give the error message, set
// rc_did_emsg and return NULL
@@ -327,7 +327,7 @@ static int reg_strict; // "[abc" is illegal
// uncrustify:off
// META[] is used often enough to justify turning it into a table.
-static char_u META_flags[] = {
+static uint8_t META_flags[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// % & ( ) * + .
@@ -361,7 +361,7 @@ static int nextchr; // used for ungetchr()
#define REG_NPAREN 3 // \%(\)
typedef struct {
- char_u *regparse;
+ char *regparse;
int prevchr_len;
int curchr;
int prevchr;
@@ -393,12 +393,12 @@ static int get_equi_class(char **pp)
{
int c;
int l = 1;
- char_u *p = (char_u *)(*pp);
+ char *p = *pp;
if (p[1] == '=' && p[2] != NUL) {
- l = utfc_ptr2len((char *)p + 2);
+ l = utfc_ptr2len(p + 2);
if (p[l + 2] == '=' && p[l + 3] == ']') {
- c = utf_ptr2char((char *)p + 2);
+ c = utf_ptr2char(p + 2);
*pp += l + 4;
return c;
}
@@ -414,12 +414,12 @@ static int get_coll_element(char **pp)
{
int c;
int l = 1;
- char_u *p = (char_u *)(*pp);
+ char *p = *pp;
if (p[0] != NUL && p[1] == '.' && p[2] != NUL) {
- l = utfc_ptr2len((char *)p + 2);
+ l = utfc_ptr2len(p + 2);
if (p[l + 2] == '.' && p[l + 3] == ']') {
- c = utf_ptr2char((char *)p + 2);
+ c = utf_ptr2char(p + 2);
*pp += l + 4;
return c;
}
@@ -437,7 +437,7 @@ static void get_cpo_flags(void)
/// Skip over a "[]" range.
/// "p" must point to the character after the '['.
/// The returned pointer is on the matching ']', or the terminating NUL.
-static char_u *skip_anyof(char *p)
+static char *skip_anyof(char *p)
{
int l;
@@ -456,9 +456,9 @@ static char_u *skip_anyof(char *p)
MB_PTR_ADV(p);
}
} else if (*p == '\\'
- && (vim_strchr(REGEXP_INRANGE, p[1]) != NULL
+ && (vim_strchr(REGEXP_INRANGE, (uint8_t)p[1]) != NULL
|| (!reg_cpo_lit
- && vim_strchr(REGEXP_ABBR, p[1]) != NULL))) {
+ && vim_strchr(REGEXP_ABBR, (uint8_t)p[1]) != NULL))) {
p += 2;
} else if (*p == '[') {
if (get_char_class(&p) == CLASS_NONE
@@ -472,7 +472,7 @@ static char_u *skip_anyof(char *p)
}
}
- return (char_u *)p;
+ return p;
}
/// Skip past regular expression.
@@ -522,7 +522,7 @@ char *skip_regexp_ex(char *startp, int dirc, int magic, char **newp, int *droppe
}
if ((p[0] == '[' && mymagic >= MAGIC_ON)
|| (p[0] == '\\' && p[1] == '[' && mymagic <= MAGIC_OFF)) {
- p = (char *)skip_anyof(p + 1);
+ p = skip_anyof(p + 1);
if (p[0] == NUL) {
break;
}
@@ -559,9 +559,9 @@ static int at_start; // True when on the first character
static int prev_at_start; // True when on the second character
// Start parsing at "str".
-static void initchr(char_u *str)
+static void initchr(char *str)
{
- regparse = (char *)str;
+ regparse = str;
prevchr_len = 0;
curchr = prevprevchr = prevchr = nextchr = -1;
at_start = true;
@@ -572,7 +572,7 @@ static void initchr(char_u *str)
// starts in the same state again.
static void save_parse_state(parse_state_T *ps)
{
- ps->regparse = (char_u *)regparse;
+ ps->regparse = regparse;
ps->prevchr_len = prevchr_len;
ps->curchr = curchr;
ps->prevchr = prevchr;
@@ -586,7 +586,7 @@ static void save_parse_state(parse_state_T *ps)
// Restore a previously saved parse state.
static void restore_parse_state(parse_state_T *ps)
{
- regparse = (char *)ps->regparse;
+ regparse = ps->regparse;
prevchr_len = ps->prevchr_len;
curchr = ps->curchr;
prevchr = ps->prevchr;
@@ -677,7 +677,7 @@ static int peekchr(void)
// '$' is only magic as the very last char and if it's in front of
// either "\|", "\)", "\&", or "\n"
if (reg_magic >= MAGIC_OFF) {
- char_u *p = (char_u *)regparse + 1;
+ uint8_t *p = (uint8_t *)regparse + 1;
bool is_magic_all = (reg_magic == MAGIC_ALL);
// ignore \c \C \m \M \v \V and \Z after '$'
@@ -892,7 +892,7 @@ static int64_t getoctchrs(void)
static int read_limits(long *minval, long *maxval)
{
int reverse = false;
- char_u *first_char;
+ char *first_char;
long tmp;
if (*regparse == '-') {
@@ -900,7 +900,7 @@ static int read_limits(long *minval, long *maxval)
regparse++;
reverse = true;
}
- first_char = (char_u *)regparse;
+ first_char = regparse;
*minval = getdigits_long(&regparse, false, 0);
if (*regparse == ',') { // There is a comma.
if (ascii_isdigit(*++regparse)) {
@@ -938,7 +938,7 @@ static int read_limits(long *minval, long *maxval)
// Sometimes need to save a copy of a line. Since alloc()/free() is very
// slow, we keep one allocated piece of memory and only re-allocate it when
// it's too small. It's freed in bt_regexec_both() when finished.
-static char_u *reg_tofree = NULL;
+static uint8_t *reg_tofree = NULL;
static unsigned reg_tofreelen;
// Structure used to store the execution state of the regex engine.
@@ -960,8 +960,8 @@ typedef struct {
regmatch_T *reg_match;
regmmatch_T *reg_mmatch;
- char_u **reg_startp;
- char_u **reg_endp;
+ uint8_t **reg_startp;
+ uint8_t **reg_endp;
lpos_T *reg_startpos;
lpos_T *reg_endpos;
@@ -973,8 +973,8 @@ typedef struct {
// The current match-position is remembered with these variables:
linenr_T lnum; ///< line number, relative to first line
- char_u *line; ///< start of current line
- char_u *input; ///< current input, points into "line"
+ uint8_t *line; ///< start of current line
+ uint8_t *input; ///< current input, points into "line"
int need_clear_subexpr; ///< subexpressions still need to be cleared
int need_clear_zsubexpr; ///< extmatch subexpressions still need to be
@@ -1019,7 +1019,7 @@ static bool reg_iswordc(int c)
}
// Get pointer to the line "lnum", which is relative to "reg_firstlnum".
-static char_u *reg_getline(linenr_T lnum)
+static char *reg_getline(linenr_T lnum)
{
// when looking behind for a match/no-match lnum is negative. But we
// can't go before line 1
@@ -1028,13 +1028,13 @@ static char_u *reg_getline(linenr_T lnum)
}
if (lnum > rex.reg_maxline) {
// Must have matched the "\n" in the last line.
- return (char_u *)"";
+ return "";
}
- return (char_u *)ml_get_buf(rex.reg_buf, rex.reg_firstlnum + lnum, false);
+ return ml_get_buf(rex.reg_buf, rex.reg_firstlnum + lnum, false);
}
-static char_u *reg_startzp[NSUBEXP]; // Workspace to mark beginning
-static char_u *reg_endzp[NSUBEXP]; // and end of \z(...\) matches
+static uint8_t *reg_startzp[NSUBEXP]; // Workspace to mark beginning
+static uint8_t *reg_endzp[NSUBEXP]; // and end of \z(...\) matches
static lpos_T reg_startzpos[NSUBEXP]; // idem, beginning pos
static lpos_T reg_endzpos[NSUBEXP]; // idem, end pos
@@ -1147,7 +1147,7 @@ static bool reg_match_visual(void)
}
// getvvcol() flushes rex.line, need to get it again
- rex.line = reg_getline(rex.lnum);
+ rex.line = (uint8_t *)reg_getline(rex.lnum);
rex.input = rex.line + col;
unsigned int cols_u = win_linetabsize(wp, rex.reg_firstlnum + rex.lnum, (char *)rex.line, col);
@@ -1184,38 +1184,42 @@ static int prog_magic_wrong(void)
// used (to increase speed).
static void cleanup_subexpr(void)
{
- if (rex.need_clear_subexpr) {
- if (REG_MULTI) {
- // Use 0xff to set lnum to -1
- memset(rex.reg_startpos, 0xff, sizeof(lpos_T) * NSUBEXP);
- memset(rex.reg_endpos, 0xff, sizeof(lpos_T) * NSUBEXP);
- } else {
- memset(rex.reg_startp, 0, sizeof(char_u *) * NSUBEXP);
- memset(rex.reg_endp, 0, sizeof(char_u *) * NSUBEXP);
- }
- rex.need_clear_subexpr = false;
+ if (!rex.need_clear_subexpr) {
+ return;
+ }
+
+ if (REG_MULTI) {
+ // Use 0xff to set lnum to -1
+ memset(rex.reg_startpos, 0xff, sizeof(lpos_T) * NSUBEXP);
+ memset(rex.reg_endpos, 0xff, sizeof(lpos_T) * NSUBEXP);
+ } else {
+ memset(rex.reg_startp, 0, sizeof(char *) * NSUBEXP);
+ memset(rex.reg_endp, 0, sizeof(char *) * NSUBEXP);
}
+ rex.need_clear_subexpr = false;
}
static void cleanup_zsubexpr(void)
{
- if (rex.need_clear_zsubexpr) {
- if (REG_MULTI) {
- // Use 0xff to set lnum to -1
- memset(reg_startzpos, 0xff, sizeof(lpos_T) * NSUBEXP);
- memset(reg_endzpos, 0xff, sizeof(lpos_T) * NSUBEXP);
- } else {
- memset(reg_startzp, 0, sizeof(char_u *) * NSUBEXP);
- memset(reg_endzp, 0, sizeof(char_u *) * NSUBEXP);
- }
- rex.need_clear_zsubexpr = false;
+ if (!rex.need_clear_zsubexpr) {
+ return;
+ }
+
+ if (REG_MULTI) {
+ // Use 0xff to set lnum to -1
+ memset(reg_startzpos, 0xff, sizeof(lpos_T) * NSUBEXP);
+ memset(reg_endzpos, 0xff, sizeof(lpos_T) * NSUBEXP);
+ } else {
+ memset(reg_startzp, 0, sizeof(char *) * NSUBEXP);
+ memset(reg_endzp, 0, sizeof(char *) * NSUBEXP);
}
+ rex.need_clear_zsubexpr = false;
}
// Advance rex.lnum, rex.line and rex.input to the next line.
static void reg_nextline(void)
{
- rex.line = reg_getline(++rex.lnum);
+ rex.line = (uint8_t *)reg_getline(++rex.lnum);
rex.input = rex.line;
fast_breakcheck();
}
@@ -1252,7 +1256,7 @@ static int match_with_backref(linenr_T start_lnum, colnr_T start_col, linenr_T e
}
// Get the line to compare with.
- p = (char *)reg_getline(clnum);
+ p = reg_getline(clnum);
assert(p);
if (clnum == end_lnum) {
@@ -1399,8 +1403,8 @@ static int cstrncmp(char *s1, char *s2, int *n)
str2 = s2;
c1 = c2 = 0;
while ((int)(str1 - s1) < *n) {
- c1 = mb_ptr2char_adv((const char_u **)&str1);
- c2 = mb_ptr2char_adv((const char_u **)&str2);
+ c1 = mb_ptr2char_adv((const char **)&str1);
+ c2 = mb_ptr2char_adv((const char **)&str2);
// decompose the character if necessary, into 'base' characters
// because I don't care about Arabic, I will hard-code the Hebrew
@@ -1434,21 +1438,21 @@ static int cstrncmp(char *s1, char *s2, int *n)
/// @param c character to find in @a s
///
/// @return NULL if no match, otherwise pointer to the position in @a s
-static inline char_u *cstrchr(const char_u *const s, const int c)
+static inline char *cstrchr(const char *const s, const int c)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
FUNC_ATTR_ALWAYS_INLINE
{
if (!rex.reg_ic) {
- return (char_u *)vim_strchr((char *)s, c);
+ return vim_strchr(s, c);
}
// Use folded case for UTF-8, slow! For ASCII use libc strpbrk which is
// expected to be highly optimized.
if (c > 0x80) {
const int folded_c = utf_fold(c);
- for (const char_u *p = s; *p != NUL; p += utfc_ptr2len((char *)p)) {
- if (utf_fold(utf_ptr2char((char *)p)) == folded_c) {
- return (char_u *)p;
+ for (const char *p = s; *p != NUL; p += utfc_ptr2len(p)) {
+ if (utf_fold(utf_ptr2char(p)) == folded_c) {
+ return (char *)p;
}
}
return NULL;
@@ -1460,11 +1464,11 @@ static inline char_u *cstrchr(const char_u *const s, const int c)
} else if (ASCII_ISLOWER(c)) {
cc = TOUPPER_ASC(c);
} else {
- return (char_u *)vim_strchr((char *)s, c);
+ return vim_strchr(s, c);
}
char tofind[] = { (char)c, (char)cc, NUL };
- return (char_u *)strpbrk((const char *)s, tofind);
+ return strpbrk(s, tofind);
}
////////////////////////////////////////////////////////////////
@@ -1636,8 +1640,7 @@ static void clear_submatch_list(staticList10_T *sl)
/// references invalid!
///
/// Returns the size of the replacement, including terminating NUL.
-int vim_regsub(regmatch_T *rmp, char_u *source, typval_T *expr, char_u *dest, int destlen,
- int flags)
+int vim_regsub(regmatch_T *rmp, char *source, typval_T *expr, char *dest, int destlen, int flags)
{
regexec_T rex_save;
bool rex_in_use_save = rex_in_use;
@@ -1653,7 +1656,7 @@ int vim_regsub(regmatch_T *rmp, char_u *source, typval_T *expr, char_u *dest, in
rex.reg_maxline = 0;
rex.reg_buf = curbuf;
rex.reg_line_lbr = true;
- int result = vim_regsub_both((char *)source, expr, (char *)dest, destlen, flags);
+ int result = vim_regsub_both(source, expr, dest, destlen, flags);
rex_in_use = rex_in_use_save;
if (rex_in_use) {
@@ -1663,7 +1666,7 @@ int vim_regsub(regmatch_T *rmp, char_u *source, typval_T *expr, char_u *dest, in
return result;
}
-int vim_regsub_multi(regmmatch_T *rmp, linenr_T lnum, char_u *source, char_u *dest, int destlen,
+int vim_regsub_multi(regmmatch_T *rmp, linenr_T lnum, char *source, char *dest, int destlen,
int flags)
{
regexec_T rex_save;
@@ -1681,7 +1684,7 @@ int vim_regsub_multi(regmmatch_T *rmp, linenr_T lnum, char_u *source, char_u *de
rex.reg_firstlnum = lnum;
rex.reg_maxline = curbuf->b_ml.ml_line_count - lnum;
rex.reg_line_lbr = false;
- int result = vim_regsub_both((char *)source, NULL, (char *)dest, destlen, flags);
+ int result = vim_regsub_both(source, NULL, dest, destlen, flags);
rex_in_use = rex_in_use_save;
if (rex_in_use) {
@@ -1860,7 +1863,7 @@ static int vim_regsub_both(char *source, typval_T *expr, char *dest, int destlen
no = 0;
} else if ('0' <= *src && *src <= '9') {
no = *src++ - '0';
- } else if (vim_strchr("uUlLeE", *src)) {
+ } else if (vim_strchr("uUlLeE", (uint8_t)(*src))) {
switch (*src++) {
case 'u':
func_one = (fptr_T)do_upper;
@@ -1974,7 +1977,7 @@ static int vim_regsub_both(char *source, typval_T *expr, char *dest, int destlen
if (clnum < 0 || rex.reg_mmatch->endpos[no].lnum < 0) {
s = NULL;
} else {
- s = (char *)reg_getline(clnum) + rex.reg_mmatch->startpos[no].col;
+ s = reg_getline(clnum) + rex.reg_mmatch->startpos[no].col;
if (rex.reg_mmatch->endpos[no].lnum == clnum) {
len = rex.reg_mmatch->endpos[no].col
- rex.reg_mmatch->startpos[no].col;
@@ -2005,7 +2008,7 @@ static int vim_regsub_both(char *source, typval_T *expr, char *dest, int destlen
*dst = CAR;
}
dst++;
- s = (char *)reg_getline(++clnum);
+ s = reg_getline(++clnum);
if (rex.reg_mmatch->endpos[no].lnum == clnum) {
len = rex.reg_mmatch->endpos[no].col;
} else {
@@ -2099,7 +2102,7 @@ static char *reg_getline_submatch(linenr_T lnum)
rex.reg_firstlnum = rsm.sm_firstlnum;
rex.reg_maxline = rsm.sm_maxline;
- s = (char *)reg_getline(lnum);
+ s = reg_getline(lnum);
rex.reg_firstlnum = save_first;
rex.reg_maxline = save_max;
@@ -2290,7 +2293,7 @@ static regengine_T nfa_regengine = {
static int regexp_engine = 0;
#ifdef REGEXP_DEBUG
-static char_u regname[][30] = {
+static uint8_t regname[][30] = {
"AUTOMATIC Regexp Engine",
"BACKTRACKING Regexp Engine",
"NFA Regexp Engine"
@@ -2339,10 +2342,10 @@ regprog_T *vim_regcomp(char *expr_arg, int re_flags)
//
const int called_emsg_before = called_emsg;
if (regexp_engine != BACKTRACKING_ENGINE) {
- prog = nfa_regengine.regcomp((char_u *)expr,
+ prog = nfa_regengine.regcomp((uint8_t *)expr,
re_flags + (regexp_engine == AUTOMATIC_ENGINE ? RE_AUTO : 0));
} else {
- prog = bt_regengine.regcomp((char_u *)expr, re_flags);
+ prog = bt_regengine.regcomp((uint8_t *)expr, re_flags);
}
// Check for error compiling regexp with initial engine.
@@ -2366,8 +2369,8 @@ regprog_T *vim_regcomp(char *expr_arg, int re_flags)
// But don't try if an error message was given.
if (regexp_engine == AUTOMATIC_ENGINE && called_emsg == called_emsg_before) {
regexp_engine = BACKTRACKING_ENGINE;
- report_re_switch((char_u *)expr);
- prog = bt_regengine.regcomp((char_u *)expr, re_flags);
+ report_re_switch(expr);
+ prog = bt_regengine.regcomp((uint8_t *)expr, re_flags);
}
}
@@ -2400,12 +2403,12 @@ void free_regexp_stuff(void)
#endif
-static void report_re_switch(char_u *pat)
+static void report_re_switch(char *pat)
{
if (p_verbose > 0) {
verbose_enter();
msg_puts(_("Switching to backtracking RE engine for pattern: "));
- msg_puts((char *)pat);
+ msg_puts(pat);
verbose_leave();
}
}
@@ -2422,7 +2425,7 @@ static void report_re_switch(char_u *pat)
/// @param nl
///
/// @return true if there is a match, false if not.
-static bool vim_regexec_string(regmatch_T *rmp, char_u *line, colnr_T col, bool nl)
+static bool vim_regexec_string(regmatch_T *rmp, char *line, colnr_T col, bool nl)
{
regexec_T rex_save;
bool rex_in_use_save = rex_in_use;
@@ -2445,7 +2448,7 @@ static bool vim_regexec_string(regmatch_T *rmp, char_u *line, colnr_T col, bool
rex.reg_startpos = NULL;
rex.reg_endpos = NULL;
- int result = rmp->regprog->engine->regexec_nl(rmp, line, col, nl);
+ int result = rmp->regprog->engine->regexec_nl(rmp, (uint8_t *)line, col, nl);
rmp->regprog->re_in_use = false;
// NFA engine aborted because it's very slow, use backtracking engine instead.
@@ -2457,11 +2460,11 @@ static bool vim_regexec_string(regmatch_T *rmp, char_u *line, colnr_T col, bool
p_re = BACKTRACKING_ENGINE;
vim_regfree(rmp->regprog);
- report_re_switch((char_u *)pat);
+ report_re_switch(pat);
rmp->regprog = vim_regcomp(pat, re_flags);
if (rmp->regprog != NULL) {
rmp->regprog->re_in_use = true;
- result = rmp->regprog->engine->regexec_nl(rmp, line, col, nl);
+ result = rmp->regprog->engine->regexec_nl(rmp, (uint8_t *)line, col, nl);
rmp->regprog->re_in_use = false;
}
@@ -2479,7 +2482,7 @@ static bool vim_regexec_string(regmatch_T *rmp, char_u *line, colnr_T col, bool
// Note: "*prog" may be freed and changed.
// Return true if there is a match, false if not.
-bool vim_regexec_prog(regprog_T **prog, bool ignore_case, char_u *line, colnr_T col)
+bool vim_regexec_prog(regprog_T **prog, bool ignore_case, char *line, colnr_T col)
{
regmatch_T regmatch = { .regprog = *prog, .rm_ic = ignore_case };
bool r = vim_regexec_string(&regmatch, line, col, false);
@@ -2491,13 +2494,13 @@ bool vim_regexec_prog(regprog_T **prog, bool ignore_case, char_u *line, colnr_T
// Return true if there is a match, false if not.
bool vim_regexec(regmatch_T *rmp, char *line, colnr_T col)
{
- return vim_regexec_string(rmp, (char_u *)line, col, false);
+ return vim_regexec_string(rmp, line, col, false);
}
// Like vim_regexec(), but consider a "\n" in "line" to be a line break.
// Note: "rmp->regprog" may be freed and changed.
// Return true if there is a match, false if not.
-bool vim_regexec_nl(regmatch_T *rmp, char_u *line, colnr_T col)
+bool vim_regexec_nl(regmatch_T *rmp, char *line, colnr_T col)
{
return vim_regexec_string(rmp, line, col, true);
}
@@ -2549,7 +2552,7 @@ long vim_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum,
p_re = BACKTRACKING_ENGINE;
regprog_T *prev_prog = rmp->regprog;
- report_re_switch((char_u *)pat);
+ report_re_switch(pat);
// checking for \z misuse was already done when compiling for NFA,
// allow all here
reg_do_extmatch = REX_ALL;
diff --git a/src/nvim/regexp_bt.c b/src/nvim/regexp_bt.c
index f930d872b6..af3d93f7c4 100644
--- a/src/nvim/regexp_bt.c
+++ b/src/nvim/regexp_bt.c
@@ -242,17 +242,17 @@
static int prevchr_len; ///< byte length of previous char
static int num_complex_braces; ///< Complex \{...} count
-static char_u *regcode; ///< Code-emit pointer, or JUST_CALC_SIZE
+static uint8_t *regcode; ///< Code-emit pointer, or JUST_CALC_SIZE
static long regsize; ///< Code size.
static int reg_toolong; ///< true when offset out of range
-static char_u had_endbrace[NSUBEXP]; ///< flags, true if end of () found
+static uint8_t had_endbrace[NSUBEXP]; ///< flags, true if end of () found
static long brace_min[10]; ///< Minimums for complex brace repeats
static long brace_max[10]; ///< Maximums for complex brace repeats
static int brace_count[10]; ///< Current counts for complex brace repeats
static int one_exactly = false; ///< only do one char for EXACTLY
// When making changes to classchars also change nfa_classcodes.
-static char_u *classchars = (char_u *)".iIkKfFpPsSdDxXoOwWhHaAlLuU";
+static uint8_t *classchars = (uint8_t *)".iIkKfFpPsSdDxXoOwWhHaAlLuU";
static int classcodes[] = {
ANY, IDENT, SIDENT, KWORD, SKWORD,
FNAME, SFNAME, PRINT, SPRINT,
@@ -265,7 +265,7 @@ static int classcodes[] = {
// When regcode is set to this value, code is not emitted and size is computed
// instead.
-#define JUST_CALC_SIZE ((char_u *)-1)
+#define JUST_CALC_SIZE ((uint8_t *)-1)
// Values for rs_state in regitem_T.
typedef enum regstate_E {
@@ -290,7 +290,7 @@ typedef enum regstate_E {
// Also stores the length of "backpos".
typedef struct {
union {
- char_u *ptr; // rex.input pointer, for single-line regexp
+ uint8_t *ptr; // rex.input pointer, for single-line regexp
lpos_T pos; // rex.input pos, for multi-line regexp
} rs_u;
int rs_len;
@@ -299,7 +299,7 @@ typedef struct {
// struct to save start/end pointer/position in for \(\)
typedef struct {
union {
- char_u *ptr;
+ uint8_t *ptr;
lpos_T pos;
} se_u;
} save_se_T;
@@ -320,7 +320,7 @@ typedef struct regbehind_S {
typedef struct regitem_S {
regstate_T rs_state; // what we are doing, one of RS_ above
int16_t rs_no; // submatch nr or BEHIND/NOBEHIND
- char_u *rs_scan; // current node in program
+ uint8_t *rs_scan; // current node in program
union {
save_se_T sesave;
regsave_T regsave;
@@ -339,7 +339,7 @@ typedef struct regstar_S {
// used to store input position when a BACK was encountered, so that we now if
// we made any progress since the last time.
typedef struct backpos_S {
- char_u *bp_scan; // "scan" where BACK was encountered
+ uint8_t *bp_scan; // "scan" where BACK was encountered
regsave_T bp_pos; // last input position
} backpos_T;
@@ -411,14 +411,14 @@ static regsave_T behind_pos;
// Obtain a second single-byte operand stored after a four bytes operand.
#define OPERAND_CMP(p) (p)[7]
-static char_u *reg(int paren, int *flagp);
+static uint8_t *reg(int paren, int *flagp);
#ifdef BT_REGEXP_DUMP
-static void regdump(char_u *, bt_regprog_T *);
+static void regdump(uint8_t *, bt_regprog_T *);
#endif
#ifdef REGEXP_DEBUG
-static char_u *regprop(char_u *);
+static uint8_t *regprop(uint8_t *);
static int regnarrate = 0;
#endif
@@ -428,9 +428,9 @@ static int regnarrate = 0;
#endif
// Setup to parse the regexp. Used once to get the length and once to do it.
-static void regcomp_start(char_u *expr, int re_flags) // see vim_regcomp()
+static void regcomp_start(uint8_t *expr, int re_flags) // see vim_regcomp()
{
- initchr(expr);
+ initchr((char *)expr);
if (re_flags & RE_MAGIC) {
reg_magic = MAGIC_ON;
} else {
@@ -466,7 +466,7 @@ static void regc(int b)
if (regcode == JUST_CALC_SIZE) {
regsize++;
} else {
- *regcode++ = (char_u)b;
+ *regcode++ = (uint8_t)b;
}
}
@@ -1453,15 +1453,15 @@ static void reg_equi_class(int c)
// Emit a node.
// Return pointer to generated code.
-static char_u *regnode(int op)
+static uint8_t *regnode(int op)
{
- char_u *ret;
+ uint8_t *ret;
ret = regcode;
if (ret == JUST_CALC_SIZE) {
regsize += 3;
} else {
- *regcode++ = (char_u)op;
+ *regcode++ = (uint8_t)op;
*regcode++ = NUL; // Null "next" pointer.
*regcode++ = NUL;
}
@@ -1469,19 +1469,19 @@ static char_u *regnode(int op)
}
// Write a four bytes number at "p" and return pointer to the next char.
-static char_u *re_put_uint32(char_u *p, uint32_t val)
+static uint8_t *re_put_uint32(uint8_t *p, uint32_t val)
{
- *p++ = (char_u)((val >> 24) & 0377);
- *p++ = (char_u)((val >> 16) & 0377);
- *p++ = (char_u)((val >> 8) & 0377);
- *p++ = (char_u)(val & 0377);
+ *p++ = (uint8_t)((val >> 24) & 0377);
+ *p++ = (uint8_t)((val >> 16) & 0377);
+ *p++ = (uint8_t)((val >> 8) & 0377);
+ *p++ = (uint8_t)(val & 0377);
return p;
}
// regnext - dig the "next" pointer out of a node
// Returns NULL when calculating size, when there is no next item and when
// there is an error.
-static char_u *regnext(char_u *p)
+static uint8_t *regnext(uint8_t *p)
FUNC_ATTR_NONNULL_ALL
{
int offset;
@@ -1503,7 +1503,7 @@ static char_u *regnext(char_u *p)
}
// Set the next-pointer at the end of a node chain.
-static void regtail(char_u *p, char_u *val)
+static void regtail(uint8_t *p, uint8_t *val)
{
int offset;
@@ -1512,9 +1512,9 @@ static void regtail(char_u *p, char_u *val)
}
// Find last node.
- char_u *scan = p;
+ uint8_t *scan = p;
for (;;) {
- char_u *temp = regnext(scan);
+ uint8_t *temp = regnext(scan);
if (temp == NULL) {
break;
}
@@ -1532,13 +1532,13 @@ static void regtail(char_u *p, char_u *val)
if (offset > 0xffff) {
reg_toolong = true;
} else {
- *(scan + 1) = (char_u)(((unsigned)offset >> 8) & 0377);
- *(scan + 2) = (char_u)(offset & 0377);
+ *(scan + 1) = (uint8_t)(((unsigned)offset >> 8) & 0377);
+ *(scan + 2) = (uint8_t)(offset & 0377);
}
}
// Like regtail, on item after a BRANCH; nop if none.
-static void regoptail(char_u *p, char_u *val)
+static void regoptail(uint8_t *p, uint8_t *val)
{
// When op is neither BRANCH nor BRACE_COMPLEX0-9, it is "operandless"
if (p == NULL || p == JUST_CALC_SIZE
@@ -1552,11 +1552,11 @@ static void regoptail(char_u *p, char_u *val)
// Insert an operator in front of already-emitted operand
//
// Means relocating the operand.
-static void reginsert(int op, char_u *opnd)
+static void reginsert(int op, uint8_t *opnd)
{
- char_u *src;
- char_u *dst;
- char_u *place;
+ uint8_t *src;
+ uint8_t *dst;
+ uint8_t *place;
if (regcode == JUST_CALC_SIZE) {
regsize += 3;
@@ -1570,18 +1570,18 @@ static void reginsert(int op, char_u *opnd)
}
place = opnd; // Op node, where operand used to be.
- *place++ = (char_u)op;
+ *place++ = (uint8_t)op;
*place++ = NUL;
*place = NUL;
}
// Insert an operator in front of already-emitted operand.
// Add a number to the operator.
-static void reginsert_nr(int op, long val, char_u *opnd)
+static void reginsert_nr(int op, long val, uint8_t *opnd)
{
- char_u *src;
- char_u *dst;
- char_u *place;
+ uint8_t *src;
+ uint8_t *dst;
+ uint8_t *place;
if (regcode == JUST_CALC_SIZE) {
regsize += 7;
@@ -1595,7 +1595,7 @@ static void reginsert_nr(int op, long val, char_u *opnd)
}
place = opnd; // Op node, where operand used to be.
- *place++ = (char_u)op;
+ *place++ = (uint8_t)op;
*place++ = NUL;
*place++ = NUL;
assert(val >= 0 && (uintmax_t)val <= UINT32_MAX);
@@ -1606,11 +1606,11 @@ static void reginsert_nr(int op, long val, char_u *opnd)
// The operator has the given limit values as operands. Also set next pointer.
//
// Means relocating the operand.
-static void reginsert_limits(int op, long minval, long maxval, char_u *opnd)
+static void reginsert_limits(int op, long minval, long maxval, uint8_t *opnd)
{
- char_u *src;
- char_u *dst;
- char_u *place;
+ uint8_t *src;
+ uint8_t *dst;
+ uint8_t *place;
if (regcode == JUST_CALC_SIZE) {
regsize += 11;
@@ -1624,7 +1624,7 @@ static void reginsert_limits(int op, long minval, long maxval, char_u *opnd)
}
place = opnd; // Op node, where operand used to be.
- *place++ = (char_u)op;
+ *place++ = (uint8_t)op;
*place++ = NUL;
*place++ = NUL;
assert(minval >= 0 && (uintmax_t)minval <= UINT32_MAX);
@@ -1641,11 +1641,11 @@ static void reginsert_limits(int op, long minval, long maxval, char_u *opnd)
static int seen_endbrace(int refnum)
{
if (!had_endbrace[refnum]) {
- char_u *p;
+ uint8_t *p;
// Trick: check if "@<=" or "@<!" follows, in which case
// the \1 can appear before the referenced match.
- for (p = (char_u *)regparse; *p != NUL; p++) {
+ for (p = (uint8_t *)regparse; *p != NUL; p++) {
if (p[0] == '@' && p[1] == '<' && (p[2] == '!' || p[2] == '=')) {
break;
}
@@ -1665,12 +1665,12 @@ static int seen_endbrace(int refnum)
// Optimization: gobbles an entire sequence of ordinary characters so that
// it can turn them into a single node, which is smaller to store and
// faster to run. Don't do this when one_exactly is set.
-static char_u *regatom(int *flagp)
+static uint8_t *regatom(int *flagp)
{
- char_u *ret;
+ uint8_t *ret;
int flags;
int c;
- char_u *p;
+ uint8_t *p;
int extra = 0;
int save_prev_at_start = prev_at_start;
@@ -1746,7 +1746,7 @@ static char_u *regatom(int *flagp)
case Magic('L'):
case Magic('u'):
case Magic('U'):
- p = (char_u *)vim_strchr((char *)classchars, no_Magic(c));
+ p = (uint8_t *)vim_strchr((char *)classchars, no_Magic(c));
if (p == NULL) {
EMSG_RET_NULL(_("E63: invalid use of \\_"));
}
@@ -1808,17 +1808,17 @@ static char_u *regatom(int *flagp)
case Magic('~'): // previous substitute pattern
if (reg_prev_sub != NULL) {
- char_u *lp;
+ uint8_t *lp;
ret = regnode(EXACTLY);
- lp = (char_u *)reg_prev_sub;
+ lp = (uint8_t *)reg_prev_sub;
while (*lp != NUL) {
regc(*lp++);
}
regc(NUL);
if (*reg_prev_sub != NUL) {
*flagp |= HASWIDTH;
- if ((lp - (char_u *)reg_prev_sub) == 1) {
+ if ((lp - (uint8_t *)reg_prev_sub) == 1) {
*flagp |= SIMPLE;
}
}
@@ -1948,9 +1948,9 @@ static char_u *regatom(int *flagp)
EMSG_ONE_RET_NULL;
}
{
- char_u *lastbranch;
- char_u *lastnode = NULL;
- char_u *br;
+ uint8_t *lastbranch;
+ uint8_t *lastnode = NULL;
+ uint8_t *br;
ret = NULL;
while ((c = getchr()) != ']') {
@@ -2072,8 +2072,8 @@ static char_u *regatom(int *flagp)
if (ret == JUST_CALC_SIZE) {
regsize += 2;
} else {
- *regcode++ = (char_u)c;
- *regcode++ = (char_u)cmp;
+ *regcode++ = (uint8_t)c;
+ *regcode++ = (uint8_t)cmp;
}
break;
} else if ((c == 'l' || c == 'c' || c == 'v') && (cur || got_digit)) {
@@ -2110,7 +2110,7 @@ static char_u *regatom(int *flagp)
// put the number and the optional
// comparator after the opcode
regcode = re_put_uint32(regcode, n);
- *regcode++ = (char_u)cmp;
+ *regcode++ = (uint8_t)cmp;
}
break;
}
@@ -2124,11 +2124,11 @@ static char_u *regatom(int *flagp)
case Magic('['):
collection:
{
- char_u *lp;
+ uint8_t *lp;
// If there is no matching ']', we assume the '[' is a normal
// character. This makes 'incsearch' and ":help [" work.
- lp = skip_anyof(regparse);
+ lp = (uint8_t *)skip_anyof(regparse);
if (*lp == ']') { // there is a matching ']'
int startc = -1; // > 0 when next '-' is a range
int endc;
@@ -2165,7 +2165,7 @@ collection:
endc = get_coll_element(&regparse);
}
if (endc == 0) {
- endc = mb_ptr2char_adv((const char_u **)&regparse);
+ endc = mb_ptr2char_adv((const char **)&regparse);
}
// Handle \o40, \x20 and \u20AC style sequences
@@ -2197,10 +2197,10 @@ collection:
// accepts "\t", "\e", etc., but only when the 'l' flag in
// 'cpoptions' is not included.
else if (*regparse == '\\'
- && (vim_strchr(REGEXP_INRANGE, regparse[1]) != NULL
+ && (vim_strchr(REGEXP_INRANGE, (uint8_t)regparse[1]) != NULL
|| (!reg_cpo_lit
&& vim_strchr(REGEXP_ABBR,
- regparse[1]) != NULL))) {
+ (uint8_t)regparse[1]) != NULL))) {
regparse++;
if (*regparse == 'n') {
// '\n' in range: also match NL
@@ -2460,11 +2460,11 @@ do_multibyte:
// both the endmarker for their branch list and the body of the last branch.
// It might seem that this node could be dispensed with entirely, but the
// endmarker role is not redundant.
-static char_u *regpiece(int *flagp)
+static uint8_t *regpiece(int *flagp)
{
- char_u *ret;
+ uint8_t *ret;
int op;
- char_u *next;
+ uint8_t *next;
int flags;
long minval;
long maxval;
@@ -2597,11 +2597,11 @@ static char_u *regpiece(int *flagp)
// Parse one alternative of an | or & operator.
// Implements the concatenation operator.
-static char_u *regconcat(int *flagp)
+static uint8_t *regconcat(int *flagp)
{
- char_u *first = NULL;
- char_u *chain = NULL;
- char_u *latest;
+ uint8_t *first = NULL;
+ uint8_t *chain = NULL;
+ uint8_t *latest;
int flags;
int cont = true;
@@ -2673,11 +2673,11 @@ static char_u *regconcat(int *flagp)
// Parse one alternative of an | operator.
// Implements the & operator.
-static char_u *regbranch(int *flagp)
+static uint8_t *regbranch(int *flagp)
{
- char_u *ret;
- char_u *chain = NULL;
- char_u *latest;
+ uint8_t *ret;
+ uint8_t *chain = NULL;
+ uint8_t *latest;
int flags;
*flagp = WORST | HASNL; // Tentatively.
@@ -2722,11 +2722,11 @@ static char_u *regbranch(int *flagp)
/// follows makes it hard to avoid.
///
/// @param paren REG_NOPAREN, REG_PAREN, REG_NPAREN or REG_ZPAREN
-static char_u *reg(int paren, int *flagp)
+static uint8_t *reg(int paren, int *flagp)
{
- char_u *ret;
- char_u *br;
- char_u *ender;
+ uint8_t *ret;
+ uint8_t *br;
+ uint8_t *ender;
int parno = 0;
int flags;
@@ -2840,10 +2840,10 @@ static char_u *reg(int paren, int *flagp)
// Beware that the optimization-preparation code in here knows about some
// of the structure of the compiled regexp.
// "re_flags": RE_MAGIC and/or RE_STRING.
-static regprog_T *bt_regcomp(char_u *expr, int re_flags)
+static regprog_T *bt_regcomp(uint8_t *expr, int re_flags)
{
- char_u *scan;
- char_u *longest;
+ uint8_t *scan;
+ uint8_t *longest;
int len;
int flags;
@@ -2862,7 +2862,7 @@ static regprog_T *bt_regcomp(char_u *expr, int re_flags)
}
// Allocate space.
- bt_regprog_T *r = xmalloc(sizeof(bt_regprog_T) + (size_t)regsize);
+ bt_regprog_T *r = xmalloc(offsetof(bt_regprog_T, program) + (size_t)regsize);
r->re_in_use = false;
// Second pass: emit code.
@@ -2890,7 +2890,7 @@ static regprog_T *bt_regcomp(char_u *expr, int re_flags)
r->regflags |= RF_LOOKBH;
}
// Remember whether this pattern has any \z specials in it.
- r->reghasz = (char_u)re_has_z;
+ r->reghasz = (uint8_t)re_has_z;
scan = r->program + 1; // First BRANCH.
if (OP(regnext(scan)) == END) { // Only one top-level choice.
scan = OPERAND(scan);
@@ -2908,7 +2908,7 @@ static regprog_T *bt_regcomp(char_u *expr, int re_flags)
|| OP(scan) == NOTHING
|| OP(scan) == MOPEN + 0 || OP(scan) == NOPEN
|| OP(scan) == MCLOSE + 0 || OP(scan) == NCLOSE) {
- char_u *regnext_scan = regnext(scan);
+ uint8_t *regnext_scan = regnext(scan);
if (OP(regnext_scan) == EXACTLY) {
r->regstart = utf_ptr2char((char *)OPERAND(regnext_scan));
}
@@ -3014,7 +3014,7 @@ static void reg_restore(regsave_T *save, garray_T *gap)
// only call reg_getline() when the line number changed to save
// a bit of time
rex.lnum = save->rs_u.pos.lnum;
- rex.line = reg_getline(rex.lnum);
+ rex.line = (uint8_t *)reg_getline(rex.lnum);
}
rex.input = rex.line + save->rs_u.pos.col;
} else {
@@ -3057,7 +3057,7 @@ static void save_se_multi(save_se_T *savep, lpos_T *posp)
posp->col = (colnr_T)(rex.input - rex.line);
}
-static void save_se_one(save_se_T *savep, char_u **pp)
+static void save_se_one(save_se_T *savep, uint8_t **pp)
{
savep->se_u.ptr = *pp;
*pp = rex.input;
@@ -3067,14 +3067,14 @@ static void save_se_one(save_se_T *savep, char_u **pp)
/// Advances rex.input (and rex.lnum) to just after the matched chars.
///
/// @param maxcount maximum number of matches allowed
-static int regrepeat(char_u *p, long maxcount)
+static int regrepeat(uint8_t *p, long maxcount)
{
long count = 0;
- char_u *opnd;
+ uint8_t *opnd;
int mask;
int testval = 0;
- char_u *scan = rex.input; // Make local copy of rex.input for speed.
+ uint8_t *scan = rex.input; // Make local copy of rex.input for speed.
opnd = OPERAND(p);
switch (OP(p)) {
case ANY:
@@ -3385,12 +3385,12 @@ do_class:
} else if (rex.reg_line_lbr && *scan == '\n' && WITH_NL(OP(p))) {
scan++;
} else if ((len = utfc_ptr2len((char *)scan)) > 1) {
- if ((cstrchr(opnd, utf_ptr2char((char *)scan)) == NULL) == testval) {
+ if ((cstrchr((char *)opnd, utf_ptr2char((char *)scan)) == NULL) == testval) {
break;
}
scan += len;
} else {
- if ((cstrchr(opnd, *scan) == NULL) == testval) {
+ if ((cstrchr((char *)opnd, *scan) == NULL) == testval) {
break;
}
scan++;
@@ -3431,7 +3431,7 @@ do_class:
// Push an item onto the regstack.
// Returns pointer to new item. Returns NULL when out of memory.
-static regitem_T *regstack_push(regstate_T state, char_u *scan)
+static regitem_T *regstack_push(regstate_T state, uint8_t *scan)
{
regitem_T *rp;
@@ -3450,7 +3450,7 @@ static regitem_T *regstack_push(regstate_T state, char_u *scan)
}
// Pop an item from the regstack.
-static void regstack_pop(char_u **scan)
+static void regstack_pop(uint8_t **scan)
{
regitem_T *rp;
@@ -3468,15 +3468,17 @@ static void save_subexpr(regbehind_T *bp)
// When "rex.need_clear_subexpr" is set we don't need to save the values, only
// remember that this flag needs to be set again when restoring.
bp->save_need_clear_subexpr = rex.need_clear_subexpr;
- if (!rex.need_clear_subexpr) {
- for (int i = 0; i < NSUBEXP; i++) {
- if (REG_MULTI) {
- bp->save_start[i].se_u.pos = rex.reg_startpos[i];
- bp->save_end[i].se_u.pos = rex.reg_endpos[i];
- } else {
- bp->save_start[i].se_u.ptr = rex.reg_startp[i];
- bp->save_end[i].se_u.ptr = rex.reg_endp[i];
- }
+ if (rex.need_clear_subexpr) {
+ return;
+ }
+
+ for (int i = 0; i < NSUBEXP; i++) {
+ if (REG_MULTI) {
+ bp->save_start[i].se_u.pos = rex.reg_startpos[i];
+ bp->save_end[i].se_u.pos = rex.reg_endpos[i];
+ } else {
+ bp->save_start[i].se_u.ptr = rex.reg_startp[i];
+ bp->save_end[i].se_u.ptr = rex.reg_endp[i];
}
}
}
@@ -3487,15 +3489,17 @@ static void restore_subexpr(regbehind_T *bp)
{
// Only need to restore saved values when they are not to be cleared.
rex.need_clear_subexpr = bp->save_need_clear_subexpr;
- if (!rex.need_clear_subexpr) {
- for (int i = 0; i < NSUBEXP; i++) {
- if (REG_MULTI) {
- rex.reg_startpos[i] = bp->save_start[i].se_u.pos;
- rex.reg_endpos[i] = bp->save_end[i].se_u.pos;
- } else {
- rex.reg_startp[i] = bp->save_start[i].se_u.ptr;
- rex.reg_endp[i] = bp->save_end[i].se_u.ptr;
- }
+ if (rex.need_clear_subexpr) {
+ return;
+ }
+
+ for (int i = 0; i < NSUBEXP; i++) {
+ if (REG_MULTI) {
+ rex.reg_startpos[i] = bp->save_start[i].se_u.pos;
+ rex.reg_endpos[i] = bp->save_end[i].se_u.pos;
+ } else {
+ rex.reg_startp[i] = bp->save_start[i].se_u.ptr;
+ rex.reg_endp[i] = bp->save_end[i].se_u.ptr;
}
}
}
@@ -3516,9 +3520,9 @@ static void restore_subexpr(regbehind_T *bp)
/// just after the last matched character.
/// - false when there is no match. Leaves rex.input and rex.lnum in an
/// undefined state!
-static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
+static bool regmatch(uint8_t *scan, proftime_T *tm, int *timed_out)
{
- char_u *next; // Next node.
+ uint8_t *next; // Next node.
int op;
int c;
regitem_T *rp;
@@ -3647,7 +3651,7 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
// Line may have been freed, get it again.
if (REG_MULTI) {
- rex.line = reg_getline(rex.lnum);
+ rex.line = (uint8_t *)reg_getline(rex.lnum);
rex.input = rex.line + col;
}
@@ -3961,7 +3965,7 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
case EXACTLY: {
int len;
- char_u *opnd;
+ uint8_t *opnd;
opnd = OPERAND(scan);
// Inline the first byte, for speed.
@@ -4003,7 +4007,7 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
case ANYBUT:
if (c == NUL) {
status = RA_NOMATCH;
- } else if ((cstrchr(OPERAND(scan), c) == NULL) == (op == ANYOF)) {
+ } else if ((cstrchr((char *)OPERAND(scan), c) == NULL) == (op == ANYOF)) {
status = RA_NOMATCH;
} else {
ADVANCE_REGINPUT();
@@ -4013,7 +4017,7 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
case MULTIBYTECODE: {
int i, len;
- const char_u *opnd = OPERAND(scan);
+ const uint8_t *opnd = OPERAND(scan);
// Safety check (just in case 'encoding' was changed since
// compiling the program).
if ((len = utfc_ptr2len((char *)opnd)) < 2) {
@@ -4699,8 +4703,8 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
(colnr_T)strlen((char *)rex.line);
}
} else {
- const char_u *const line =
- reg_getline(rp->rs_un.regsave.rs_u.pos.lnum);
+ const uint8_t *const line =
+ (uint8_t *)reg_getline(rp->rs_un.regsave.rs_u.pos.lnum);
rp->rs_un.regsave.rs_u.pos.col -=
utf_head_off((char *)line,
@@ -4782,7 +4786,7 @@ static bool regmatch(char_u *scan, proftime_T *tm, int *timed_out)
break;
}
rex.lnum--;
- rex.line = reg_getline(rex.lnum);
+ rex.line = (uint8_t *)reg_getline(rex.lnum);
// Just in case regrepeat() didn't count right.
if (rex.line == NULL) {
break;
@@ -4913,13 +4917,13 @@ static long regtry(bt_regprog_T *prog, colnr_T col, proftime_T *tm, int *timed_o
&& reg_endzpos[i].lnum == reg_startzpos[i].lnum
&& reg_endzpos[i].col >= reg_startzpos[i].col) {
re_extmatch_out->matches[i] =
- (char_u *)xstrnsave((char *)reg_getline(reg_startzpos[i].lnum) + reg_startzpos[i].col,
- (size_t)(reg_endzpos[i].col - reg_startzpos[i].col));
+ (uint8_t *)xstrnsave((char *)reg_getline(reg_startzpos[i].lnum) + reg_startzpos[i].col,
+ (size_t)(reg_endzpos[i].col - reg_startzpos[i].col));
}
} else {
if (reg_startzp[i] != NULL && reg_endzp[i] != NULL) {
re_extmatch_out->matches[i] =
- (char_u *)xstrnsave((char *)reg_startzp[i], (size_t)(reg_endzp[i] - reg_startzp[i]));
+ (uint8_t *)xstrnsave((char *)reg_startzp[i], (size_t)(reg_endzp[i] - reg_startzp[i]));
}
}
}
@@ -4935,10 +4939,10 @@ static long regtry(bt_regprog_T *prog, colnr_T col, proftime_T *tm, int *timed_o
/// @param timed_out flag set on timeout or NULL
///
/// @return 0 for failure, or number of lines contained in the match.
-static long bt_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm, int *timed_out)
+static long bt_regexec_both(uint8_t *line, colnr_T startcol, proftime_T *tm, int *timed_out)
{
bt_regprog_T *prog;
- char_u *s;
+ uint8_t *s;
colnr_T col = startcol;
long retval = 0L;
@@ -4962,13 +4966,13 @@ static long bt_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm, int
if (REG_MULTI) {
prog = (bt_regprog_T *)rex.reg_mmatch->regprog;
- line = reg_getline((linenr_T)0);
+ line = (uint8_t *)reg_getline((linenr_T)0);
rex.reg_startpos = rex.reg_mmatch->startpos;
rex.reg_endpos = rex.reg_mmatch->endpos;
} else {
prog = (bt_regprog_T *)rex.reg_match->regprog;
- rex.reg_startp = (char_u **)rex.reg_match->startp;
- rex.reg_endp = (char_u **)rex.reg_match->endp;
+ rex.reg_startp = (uint8_t **)rex.reg_match->startp;
+ rex.reg_endp = (uint8_t **)rex.reg_match->endp;
}
// Be paranoid...
@@ -5007,14 +5011,14 @@ static long bt_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm, int
// This is used very often, esp. for ":global". Use two versions of
// the loop to avoid overhead of conditions.
if (!rex.reg_ic) {
- while ((s = (char_u *)vim_strchr((char *)s, c)) != NULL) {
+ while ((s = (uint8_t *)vim_strchr((char *)s, c)) != NULL) {
if (cstrncmp((char *)s, (char *)prog->regmust, &prog->regmlen) == 0) {
break; // Found it.
}
MB_PTR_ADV(s);
}
} else {
- while ((s = cstrchr(s, c)) != NULL) {
+ while ((s = (uint8_t *)cstrchr((char *)s, c)) != NULL) {
if (cstrncmp((char *)s, (char *)prog->regmust, &prog->regmlen) == 0) {
break; // Found it.
}
@@ -5049,7 +5053,7 @@ static long bt_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm, int
while (!got_int) {
if (prog->regstart != NUL) {
// Skip until the char we know it must start with.
- s = cstrchr(rex.line + col, prog->regstart);
+ s = (uint8_t *)cstrchr((char *)rex.line + col, prog->regstart);
if (s == NULL) {
retval = 0;
break;
@@ -5071,7 +5075,7 @@ static long bt_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm, int
// if not currently on the first line, get it again
if (rex.lnum != 0) {
rex.lnum = 0;
- rex.line = reg_getline((linenr_T)0);
+ rex.line = (uint8_t *)reg_getline((linenr_T)0);
}
if (rex.line[col] == NUL) {
break;
@@ -5141,7 +5145,7 @@ theend:
/// @param col column to start looking for match
///
/// @return 0 for failure, number of lines contained in the match otherwise.
-static int bt_regexec_nl(regmatch_T *rmp, char_u *line, colnr_T col, bool line_lbr)
+static int bt_regexec_nl(regmatch_T *rmp, uint8_t *line, colnr_T col, bool line_lbr)
{
rex.reg_match = rmp;
rex.reg_mmatch = NULL;
@@ -5178,7 +5182,7 @@ static long bt_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T
}
// Compare a number with the operand of RE_LNUM, RE_COL or RE_VCOL.
-static int re_num_cmp(uint32_t val, char_u *scan)
+static int re_num_cmp(uint32_t val, uint8_t *scan)
{
uint32_t n = (uint32_t)OPERAND_MIN(scan);
@@ -5194,12 +5198,12 @@ static int re_num_cmp(uint32_t val, char_u *scan)
#ifdef BT_REGEXP_DUMP
// regdump - dump a regexp onto stdout in vaguely comprehensible form
-static void regdump(char_u *pattern, bt_regprog_T *r)
+static void regdump(uint8_t *pattern, bt_regprog_T *r)
{
- char_u *s;
+ uint8_t *s;
int op = EXACTLY; // Arbitrary non-END op.
- char_u *next;
- char_u *end = NULL;
+ uint8_t *next;
+ uint8_t *end = NULL;
FILE *f;
# ifdef BT_REGEXP_LOG
@@ -5280,7 +5284,7 @@ static void regdump(char_u *pattern, bt_regprog_T *r)
#ifdef REGEXP_DEBUG
// regprop - printable representation of opcode
-static char_u *regprop(char_u *op)
+static uint8_t *regprop(uint8_t *op)
{
char *p;
static char buf[50];
@@ -5652,6 +5656,6 @@ static char_u *regprop(char_u *op)
if (p != NULL) {
STRCAT(buf, p);
}
- return (char_u *)buf;
+ return (uint8_t *)buf;
}
#endif // REGEXP_DEBUG
diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c
index 6e7ff31c03..ea59e7d464 100644
--- a/src/nvim/regexp_nfa.c
+++ b/src/nvim/regexp_nfa.c
@@ -244,10 +244,10 @@ static int nfa_classcodes[] = {
NFA_UPPER, NFA_NUPPER
};
-static char_u e_nul_found[] = N_("E865: (NFA) Regexp end encountered prematurely");
-static char_u e_misplaced[] = N_("E866: (NFA regexp) Misplaced %c");
-static char_u e_ill_char_class[] = N_("E877: (NFA regexp) Invalid character class: %" PRId64);
-static char_u e_value_too_large[] = N_("E951: \\% value too large");
+static char e_nul_found[] = N_("E865: (NFA) Regexp end encountered prematurely");
+static char e_misplaced[] = N_("E866: (NFA regexp) Misplaced %c");
+static char e_ill_char_class[] = N_("E877: (NFA regexp) Invalid character class: %" PRId64);
+static char e_value_too_large[] = N_("E951: \\% value too large");
// Since the out pointers in the list are always
// uninitialized, we use the pointers themselves
@@ -276,8 +276,8 @@ typedef struct {
colnr_T end_col;
} multi[NSUBEXP];
struct linepos {
- char_u *start;
- char_u *end;
+ uint8_t *start;
+ uint8_t *end;
} line[NSUBEXP];
} list;
colnr_T orig_start_col; // list.multi[0].start_col without \zs
@@ -296,7 +296,7 @@ struct nfa_pim_S {
regsubs_T subs; // submatch info, only party used
union {
lpos_T pos;
- char_u *ptr;
+ uint8_t *ptr;
} end; // where the match must end
};
@@ -354,7 +354,7 @@ static int nfa_ll_index = 0;
/// Initialize internal variables before NFA compilation.
///
/// @param re_flags @see vim_regcomp()
-static void nfa_regcomp_start(char_u *expr, int re_flags)
+static void nfa_regcomp_start(uint8_t *expr, int re_flags)
{
size_t postfix_size;
size_t nstate_max;
@@ -519,12 +519,12 @@ static int nfa_get_regstart(nfa_state_T *start, int depth)
// Figure out if the NFA state list contains just literal text and nothing
// else. If so return a string in allocated memory with what must match after
// regstart. Otherwise return NULL.
-static char_u *nfa_get_match_text(nfa_state_T *start)
+static uint8_t *nfa_get_match_text(nfa_state_T *start)
{
nfa_state_T *p = start;
int len = 0;
- char_u *ret;
- char_u *s;
+ uint8_t *ret;
+ uint8_t *s;
if (p->c != NFA_MOPEN) {
return NULL; // just in case
@@ -571,7 +571,7 @@ static void realloc_post_list(void)
// to the closing brace.
// Keep in mind that 'ignorecase' applies at execution time, thus [a-z] may
// need to be interpreted as [a-zA-Z].
-static int nfa_recognize_char_class(char_u *start, char_u *end, int extra_newl)
+static int nfa_recognize_char_class(uint8_t *start, uint8_t *end, int extra_newl)
{
#define CLASS_not 0x80
#define CLASS_af 0x40
@@ -582,7 +582,7 @@ static int nfa_recognize_char_class(char_u *start, char_u *end, int extra_newl)
#define CLASS_o9 0x02
#define CLASS_underscore 0x01
- char_u *p;
+ uint8_t *p;
int config = 0;
bool newl = extra_newl == true;
@@ -1788,9 +1788,9 @@ static int nfa_regatom(void)
int equiclass;
int collclass;
int got_coll_char;
- char_u *p;
- char_u *endp;
- char_u *old_regparse = (char_u *)regparse;
+ uint8_t *p;
+ uint8_t *endp;
+ uint8_t *old_regparse = (uint8_t *)regparse;
int extra = 0;
int emit_range;
int negated;
@@ -1873,7 +1873,7 @@ static int nfa_regatom(void)
case Magic('L'):
case Magic('u'):
case Magic('U'):
- p = (char_u *)vim_strchr((char *)classchars, no_Magic(c));
+ p = (uint8_t *)vim_strchr((char *)classchars, no_Magic(c));
if (p == NULL) {
if (extra == NFA_ADD_NL) {
semsg(_(e_ill_char_class), (int64_t)c);
@@ -1886,7 +1886,7 @@ static int nfa_regatom(void)
// When '.' is followed by a composing char ignore the dot, so that
// the composing char is matched here.
if (c == Magic('.') && utf_iscomposing(peekchr())) {
- old_regparse = (char_u *)regparse;
+ old_regparse = (uint8_t *)regparse;
c = getchr();
goto nfa_do_multibyte;
}
@@ -1932,7 +1932,7 @@ static int nfa_regatom(void)
return FAIL;
case Magic('~'): {
- char_u *lp;
+ uint8_t *lp;
// Previous substitute pattern.
// Generated as "\%(pattern\)".
@@ -1940,9 +1940,9 @@ static int nfa_regatom(void)
emsg(_(e_nopresub));
return FAIL;
}
- for (lp = (char_u *)reg_prev_sub; *lp != NUL; MB_CPTR_ADV(lp)) {
+ for (lp = (uint8_t *)reg_prev_sub; *lp != NUL; MB_CPTR_ADV(lp)) {
EMIT(utf_ptr2char((char *)lp));
- if (lp != (char_u *)reg_prev_sub) {
+ if (lp != (uint8_t *)reg_prev_sub) {
EMIT(NFA_CONCAT);
}
}
@@ -2217,13 +2217,13 @@ collection:
// - character classes NFA_CLASS_*
// - ranges, two characters followed by NFA_RANGE.
- p = (char_u *)regparse;
- endp = skip_anyof((char *)p);
+ p = (uint8_t *)regparse;
+ endp = (uint8_t *)skip_anyof((char *)p);
if (*endp == ']') {
// Try to reverse engineer character classes. For example,
// recognize that [0-9] stands for \d and [A-Za-z_] for \h,
// and perform the necessary substitutions in the NFA.
- int result = nfa_recognize_char_class((char_u *)regparse, endp, extra == NFA_ADD_NL);
+ int result = nfa_recognize_char_class((uint8_t *)regparse, endp, extra == NFA_ADD_NL);
if (result != FAIL) {
if (result >= NFA_FIRST_NL && result <= NFA_LAST_NL) {
EMIT(result - NFA_ADD_NL);
@@ -2255,7 +2255,7 @@ collection:
}
// Emit the OR branches for each character in the []
emit_range = false;
- while ((char_u *)regparse < endp) {
+ while ((uint8_t *)regparse < endp) {
int oldstartc = startc;
startc = -1;
got_coll_char = false;
@@ -2362,10 +2362,10 @@ collection:
// accepts "\t", "\e", etc., but only when the 'l' flag in
// 'cpoptions' is not included.
if (*regparse == '\\'
- && (char_u *)regparse + 1 <= endp
- && (vim_strchr(REGEXP_INRANGE, regparse[1]) != NULL
+ && (uint8_t *)regparse + 1 <= endp
+ && (vim_strchr(REGEXP_INRANGE, (uint8_t)regparse[1]) != NULL
|| (!reg_cpo_lit
- && vim_strchr(REGEXP_ABBR, regparse[1])
+ && vim_strchr(REGEXP_ABBR, (uint8_t)regparse[1])
!= NULL))) {
MB_PTR_ADV(regparse);
@@ -2927,7 +2927,7 @@ static int nfa_reg(int paren)
}
#ifdef REGEXP_DEBUG
-static char_u code[50];
+static uint8_t code[50];
static void nfa_set_code(int c)
{
@@ -3275,35 +3275,37 @@ static void nfa_set_code(int c)
}
static FILE *log_fd;
-static char_u e_log_open_failed[] =
+static uint8_t e_log_open_failed[] =
N_("Could not open temporary log file for writing, displaying on stderr... ");
// Print the postfix notation of the current regexp.
-static void nfa_postfix_dump(char_u *expr, int retval)
+static void nfa_postfix_dump(uint8_t *expr, int retval)
{
int *p;
FILE *f;
f = fopen(NFA_REGEXP_DUMP_LOG, "a");
- if (f != NULL) {
- fprintf(f, "\n-------------------------\n");
- if (retval == FAIL) {
- fprintf(f, ">>> NFA engine failed... \n");
- } else if (retval == OK) {
- fprintf(f, ">>> NFA engine succeeded !\n");
- }
- fprintf(f, "Regexp: \"%s\"\nPostfix notation (char): \"", expr);
- for (p = post_start; *p && p < post_ptr; p++) {
- nfa_set_code(*p);
- fprintf(f, "%s, ", code);
- }
- fprintf(f, "\"\nPostfix notation (int): ");
- for (p = post_start; *p && p < post_ptr; p++) {
- fprintf(f, "%d ", *p);
- }
- fprintf(f, "\n\n");
- fclose(f);
+ if (f == NULL) {
+ return;
}
+
+ fprintf(f, "\n-------------------------\n");
+ if (retval == FAIL) {
+ fprintf(f, ">>> NFA engine failed... \n");
+ } else if (retval == OK) {
+ fprintf(f, ">>> NFA engine succeeded !\n");
+ }
+ fprintf(f, "Regexp: \"%s\"\nPostfix notation (char): \"", expr);
+ for (p = post_start; *p && p < post_ptr; p++) {
+ nfa_set_code(*p);
+ fprintf(f, "%s, ", code);
+ }
+ fprintf(f, "\"\nPostfix notation (int): ");
+ for (p = post_start; *p && p < post_ptr; p++) {
+ fprintf(f, "%d ", *p);
+ }
+ fprintf(f, "\n\n");
+ fclose(f);
}
// Print the NFA starting with a root node "state".
@@ -3319,7 +3321,7 @@ static void nfa_print_state(FILE *debugf, nfa_state_T *state)
static void nfa_print_state2(FILE *debugf, nfa_state_T *state, garray_T *indent)
{
- char_u *p;
+ uint8_t *p;
if (state == NULL) {
return;
@@ -3328,10 +3330,10 @@ static void nfa_print_state2(FILE *debugf, nfa_state_T *state, garray_T *indent)
fprintf(debugf, "(%2d)", abs(state->id));
// Output indent
- p = (char_u *)indent->ga_data;
+ p = (uint8_t *)indent->ga_data;
if (indent->ga_len >= 3) {
int last = indent->ga_len - 3;
- char_u save[2];
+ uint8_t save[2];
strncpy(save, &p[last], 2); // NOLINT(runtime/printf)
memcpy(&p[last], "+-", 2);
@@ -3356,9 +3358,9 @@ static void nfa_print_state2(FILE *debugf, nfa_state_T *state, garray_T *indent)
// grow indent for state->out
indent->ga_len -= 1;
if (state->out1) {
- ga_concat(indent, (char_u *)"| ");
+ ga_concat(indent, (uint8_t *)"| ");
} else {
- ga_concat(indent, (char_u *)" ");
+ ga_concat(indent, (uint8_t *)" ");
}
ga_append(indent, NUL);
@@ -3366,7 +3368,7 @@ static void nfa_print_state2(FILE *debugf, nfa_state_T *state, garray_T *indent)
// replace last part of indent for state->out1
indent->ga_len -= 3;
- ga_concat(indent, (char_u *)" ");
+ ga_concat(indent, (uint8_t *)" ");
ga_append(indent, NUL);
nfa_print_state2(debugf, state->out1, indent);
@@ -3381,22 +3383,24 @@ static void nfa_dump(nfa_regprog_T *prog)
{
FILE *debugf = fopen(NFA_REGEXP_DUMP_LOG, "a");
- if (debugf != NULL) {
- nfa_print_state(debugf, prog->start);
+ if (debugf == NULL) {
+ return;
+ }
- if (prog->reganch) {
- fprintf(debugf, "reganch: %d\n", prog->reganch);
- }
- if (prog->regstart != NUL) {
- fprintf(debugf, "regstart: %c (decimal: %d)\n",
- prog->regstart, prog->regstart);
- }
- if (prog->match_text != NULL) {
- fprintf(debugf, "match_text: \"%s\"\n", prog->match_text);
- }
+ nfa_print_state(debugf, prog->start);
- fclose(debugf);
+ if (prog->reganch) {
+ fprintf(debugf, "reganch: %d\n", prog->reganch);
+ }
+ if (prog->regstart != NUL) {
+ fprintf(debugf, "regstart: %c (decimal: %d)\n",
+ prog->regstart, prog->regstart);
}
+ if (prog->match_text != NULL) {
+ fprintf(debugf, "match_text: \"%s\"\n", prog->match_text);
+ }
+
+ fclose(debugf);
}
#endif // REGEXP_DEBUG
@@ -4427,16 +4431,18 @@ static void clear_sub(regsub_T *sub)
static void copy_sub(regsub_T *to, regsub_T *from)
{
to->in_use = from->in_use;
- if (from->in_use > 0) {
- // Copy the match start and end positions.
- if (REG_MULTI) {
- memmove(&to->list.multi[0], &from->list.multi[0],
- sizeof(struct multipos) * (size_t)from->in_use);
- to->orig_start_col = from->orig_start_col;
- } else {
- memmove(&to->list.line[0], &from->list.line[0],
- sizeof(struct linepos) * (size_t)from->in_use);
- }
+ if (from->in_use <= 0) {
+ return;
+ }
+
+ // Copy the match start and end positions.
+ if (REG_MULTI) {
+ memmove(&to->list.multi[0], &from->list.multi[0],
+ sizeof(struct multipos) * (size_t)from->in_use);
+ to->orig_start_col = from->orig_start_col;
+ } else {
+ memmove(&to->list.line[0], &from->list.line[0],
+ sizeof(struct linepos) * (size_t)from->in_use);
}
}
@@ -4446,31 +4452,35 @@ static void copy_sub_off(regsub_T *to, regsub_T *from)
if (to->in_use < from->in_use) {
to->in_use = from->in_use;
}
- if (from->in_use > 1) {
- // Copy the match start and end positions.
- if (REG_MULTI) {
- memmove(&to->list.multi[1], &from->list.multi[1],
- sizeof(struct multipos) * (size_t)(from->in_use - 1));
- } else {
- memmove(&to->list.line[1], &from->list.line[1],
- sizeof(struct linepos) * (size_t)(from->in_use - 1));
- }
+ if (from->in_use <= 1) {
+ return;
+ }
+
+ // Copy the match start and end positions.
+ if (REG_MULTI) {
+ memmove(&to->list.multi[1], &from->list.multi[1],
+ sizeof(struct multipos) * (size_t)(from->in_use - 1));
+ } else {
+ memmove(&to->list.line[1], &from->list.line[1],
+ sizeof(struct linepos) * (size_t)(from->in_use - 1));
}
}
// Like copy_sub() but only do the end of the main match if \ze is present.
static void copy_ze_off(regsub_T *to, regsub_T *from)
{
- if (rex.nfa_has_zend) {
- if (REG_MULTI) {
- if (from->list.multi[0].end_lnum >= 0) {
- to->list.multi[0].end_lnum = from->list.multi[0].end_lnum;
- to->list.multi[0].end_col = from->list.multi[0].end_col;
- }
- } else {
- if (from->list.line[0].end != NULL) {
- to->list.line[0].end = from->list.line[0].end;
- }
+ if (!rex.nfa_has_zend) {
+ return;
+ }
+
+ if (REG_MULTI) {
+ if (from->list.multi[0].end_lnum >= 0) {
+ to->list.multi[0].end_lnum = from->list.multi[0].end_lnum;
+ to->list.multi[0].end_col = from->list.multi[0].end_col;
+ }
+ } else {
+ if (from->list.line[0].end != NULL) {
+ to->list.line[0].end = from->list.line[0].end;
}
}
}
@@ -4483,8 +4493,8 @@ static bool sub_equal(regsub_T *sub1, regsub_T *sub2)
int todo;
linenr_T s1;
linenr_T s2;
- char_u *sp1;
- char_u *sp2;
+ uint8_t *sp1;
+ uint8_t *sp2;
todo = sub1->in_use > sub2->in_use ? sub1->in_use : sub2->in_use;
if (REG_MULTI) {
@@ -4779,7 +4789,7 @@ static regsubs_T *addstate(nfa_list_T *l, nfa_state_T *state, regsubs_T *subs_ar
nfa_thread_T *thread;
struct multipos save_multipos;
int save_in_use;
- char_u *save_ptr;
+ uint8_t *save_ptr;
int i;
regsub_T *sub;
regsubs_T *subs = subs_arg;
@@ -5522,10 +5532,10 @@ static int recursive_regmatch(nfa_state_T *state, nfa_pim_T *pim, nfa_regprog_T
// bytes if possible.
if (state->val <= 0) {
if (REG_MULTI) {
- rex.line = reg_getline(--rex.lnum);
+ rex.line = (uint8_t *)reg_getline(--rex.lnum);
if (rex.line == NULL) {
// can't go before the first line
- rex.line = reg_getline(++rex.lnum);
+ rex.line = (uint8_t *)reg_getline(++rex.lnum);
}
}
rex.input = rex.line;
@@ -5533,10 +5543,10 @@ static int recursive_regmatch(nfa_state_T *state, nfa_pim_T *pim, nfa_regprog_T
if (REG_MULTI && (int)(rex.input - rex.line) < state->val) {
// Not enough bytes in this line, go to end of
// previous line.
- rex.line = reg_getline(--rex.lnum);
+ rex.line = (uint8_t *)reg_getline(--rex.lnum);
if (rex.line == NULL) {
// can't go before the first line
- rex.line = reg_getline(++rex.lnum);
+ rex.line = (uint8_t *)reg_getline(++rex.lnum);
rex.input = rex.line;
} else {
rex.input = rex.line + strlen((char *)rex.line);
@@ -5595,7 +5605,7 @@ static int recursive_regmatch(nfa_state_T *state, nfa_pim_T *pim, nfa_regprog_T
// restore position in input text
rex.lnum = save_reglnum;
if (REG_MULTI) {
- rex.line = reg_getline(rex.lnum);
+ rex.line = (uint8_t *)reg_getline(rex.lnum);
}
rex.input = rex.line + save_reginput_col;
if (result != NFA_TOO_EXPENSIVE) {
@@ -5772,7 +5782,7 @@ static int failure_chance(nfa_state_T *state, int depth)
// Skip until the char "c" we know a match must start with.
static int skip_to_start(int c, colnr_T *colp)
{
- const char_u *const s = cstrchr(rex.line + *colp, c);
+ const uint8_t *const s = (uint8_t *)cstrchr((char *)rex.line + *colp, c);
if (s == NULL) {
return FAIL;
}
@@ -5783,7 +5793,7 @@ static int skip_to_start(int c, colnr_T *colp)
// Check for a match with match_text.
// Called after skip_to_start() has found regstart.
// Returns zero for no match, 1 for a match.
-static long find_match_text(colnr_T *startcol, int regstart, char_u *match_text)
+static long find_match_text(colnr_T *startcol, int regstart, uint8_t *match_text)
{
#define PTR2LEN(x) utf_ptr2len(x)
@@ -5792,8 +5802,8 @@ static long find_match_text(colnr_T *startcol, int regstart, char_u *match_text)
for (;;) {
bool match = true;
- char_u *s1 = match_text;
- char_u *s2 = rex.line + col + regstart_len; // skip regstart
+ uint8_t *s1 = match_text;
+ uint8_t *s2 = rex.line + col + regstart_len; // skip regstart
while (*s1) {
int c1_len = PTR2LEN((char *)s1);
int c1 = utf_ptr2char((char *)s1);
@@ -6860,7 +6870,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
// Line may have been freed, get it again.
if (REG_MULTI) {
- rex.line = reg_getline(rex.lnum);
+ rex.line = (uint8_t *)reg_getline(rex.lnum);
rex.input = rex.line + col;
}
@@ -7298,15 +7308,15 @@ static long nfa_regtry(nfa_regprog_T *prog, colnr_T col, proftime_T *tm, int *ti
&& mpos->start_lnum == mpos->end_lnum
&& mpos->end_col >= mpos->start_col) {
re_extmatch_out->matches[i] =
- (char_u *)xstrnsave((char *)reg_getline(mpos->start_lnum) + mpos->start_col,
- (size_t)(mpos->end_col - mpos->start_col));
+ (uint8_t *)xstrnsave((char *)reg_getline(mpos->start_lnum) + mpos->start_col,
+ (size_t)(mpos->end_col - mpos->start_col));
}
} else {
struct linepos *lpos = &subs.synt.list.line[i];
if (lpos->start != NULL && lpos->end != NULL) {
re_extmatch_out->matches[i] =
- (char_u *)xstrnsave((char *)lpos->start, (size_t)(lpos->end - lpos->start));
+ (uint8_t *)xstrnsave((char *)lpos->start, (size_t)(lpos->end - lpos->start));
}
}
}
@@ -7325,7 +7335,7 @@ static long nfa_regtry(nfa_regprog_T *prog, colnr_T col, proftime_T *tm, int *ti
///
/// @return <= 0 if there is no match and number of lines contained in the
/// match otherwise.
-static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm, int *timed_out)
+static long nfa_regexec_both(uint8_t *line, colnr_T startcol, proftime_T *tm, int *timed_out)
{
nfa_regprog_T *prog;
long retval = 0L;
@@ -7333,13 +7343,13 @@ static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm, int
if (REG_MULTI) {
prog = (nfa_regprog_T *)rex.reg_mmatch->regprog;
- line = reg_getline((linenr_T)0); // relative to the cursor
+ line = (uint8_t *)reg_getline((linenr_T)0); // relative to the cursor
rex.reg_startpos = rex.reg_mmatch->startpos;
rex.reg_endpos = rex.reg_mmatch->endpos;
} else {
prog = (nfa_regprog_T *)rex.reg_match->regprog;
- rex.reg_startp = (char_u **)rex.reg_match->startp;
- rex.reg_endp = (char_u **)rex.reg_match->endp;
+ rex.reg_startp = (uint8_t **)rex.reg_match->startp;
+ rex.reg_endp = (uint8_t **)rex.reg_match->endp;
}
// Be paranoid...
@@ -7454,7 +7464,7 @@ theend:
// Compile a regular expression into internal code for the NFA matcher.
// Returns the program in allocated space. Returns NULL for an error.
-static regprog_T *nfa_regcomp(char_u *expr, int re_flags)
+static regprog_T *nfa_regcomp(uint8_t *expr, int re_flags)
{
nfa_regprog_T *prog = NULL;
int *postfix;
@@ -7501,7 +7511,7 @@ static regprog_T *nfa_regcomp(char_u *expr, int re_flags)
post2nfa(postfix, post_ptr, true);
// allocate the regprog with space for the compiled regexp
- size_t prog_size = sizeof(nfa_regprog_T) + sizeof(nfa_state_T) * (size_t)(nstate - 1);
+ size_t prog_size = offsetof(nfa_regprog_T, state) + sizeof(nfa_state_T) * (size_t)nstate;
prog = xmalloc(prog_size);
state_ptr = prog->state;
prog->re_in_use = false;
@@ -7554,11 +7564,13 @@ fail:
// Free a compiled regexp program, returned by nfa_regcomp().
static void nfa_regfree(regprog_T *prog)
{
- if (prog != NULL) {
- xfree(((nfa_regprog_T *)prog)->match_text);
- xfree(((nfa_regprog_T *)prog)->pattern);
- xfree(prog);
+ if (prog == NULL) {
+ return;
}
+
+ xfree(((nfa_regprog_T *)prog)->match_text);
+ xfree(((nfa_regprog_T *)prog)->pattern);
+ xfree(prog);
}
/// Match a regexp against a string.
@@ -7570,7 +7582,7 @@ static void nfa_regfree(regprog_T *prog)
/// @param col column to start looking for match
///
/// @return <= 0 for failure, number of lines contained in the match otherwise.
-static int nfa_regexec_nl(regmatch_T *rmp, char_u *line, colnr_T col, bool line_lbr)
+static int nfa_regexec_nl(regmatch_T *rmp, uint8_t *line, colnr_T col, bool line_lbr)
{
rex.reg_match = rmp;
rex.reg_mmatch = NULL;
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index e009b883ca..b071e10cf9 100644
--- a/src/nvim/runtime.c
+++ b/src/nvim/runtime.c
@@ -9,7 +9,6 @@
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
-#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <uv.h>
@@ -27,6 +26,7 @@
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
+#include "nvim/garray.h"
#include "nvim/getchar.h"
#include "nvim/gettext.h"
#include "nvim/globals.h"
@@ -105,7 +105,7 @@ estack_T *estack_push(etype_T type, char *name, linenr_T lnum)
void estack_push_ufunc(ufunc_T *ufunc, linenr_T lnum)
{
estack_T *entry = estack_push(ETYPE_UFUNC,
- ufunc->uf_name_exp != NULL ? (char *)ufunc->uf_name_exp : ufunc->uf_name,
+ ufunc->uf_name_exp != NULL ? ufunc->uf_name_exp : ufunc->uf_name,
lnum);
if (entry != NULL) {
entry->es_info.ufunc = ufunc;
@@ -209,29 +209,56 @@ void runtime_init(void)
uv_mutex_init(&runtime_search_path_mutex);
}
-/// ":runtime [what] {name}"
+/// Get DIP_ flags from the [where] argument of a :runtime command.
+/// "*argp" is advanced to after the [where] argument.
+static int get_runtime_cmd_flags(char **argp, size_t where_len)
+{
+ char *arg = *argp;
+
+ if (where_len == 0) {
+ return 0;
+ }
+
+ if (strncmp(arg, "START", where_len) == 0) {
+ *argp = skipwhite(arg + where_len);
+ return DIP_START + DIP_NORTP;
+ }
+ if (strncmp(arg, "OPT", where_len) == 0) {
+ *argp = skipwhite(arg + where_len);
+ return DIP_OPT + DIP_NORTP;
+ }
+ if (strncmp(arg, "PACK", where_len) == 0) {
+ *argp = skipwhite(arg + where_len);
+ return DIP_START + DIP_OPT + DIP_NORTP;
+ }
+ if (strncmp(arg, "ALL", where_len) == 0) {
+ *argp = skipwhite(arg + where_len);
+ return DIP_START + DIP_OPT;
+ }
+
+ return 0;
+}
+
+/// ":runtime [where] {name}"
void ex_runtime(exarg_T *eap)
{
char *arg = eap->arg;
- char *p = skiptowhite(arg);
- size_t len = (size_t)(p - arg);
int flags = eap->forceit ? DIP_ALL : 0;
+ char *p = skiptowhite(arg);
+ flags += get_runtime_cmd_flags(&arg, (size_t)(p - arg));
+ source_runtime(arg, flags);
+}
- if (strncmp(arg, "START", len) == 0) {
- flags += DIP_START + DIP_NORTP;
- arg = skipwhite(arg + len);
- } else if (strncmp(arg, "OPT", len) == 0) {
- flags += DIP_OPT + DIP_NORTP;
- arg = skipwhite(arg + len);
- } else if (strncmp(arg, "PACK", len) == 0) {
- flags += DIP_START + DIP_OPT + DIP_NORTP;
- arg = skipwhite(arg + len);
- } else if (strncmp(arg, "ALL", len) == 0) {
- flags += DIP_START + DIP_OPT;
- arg = skipwhite(arg + len);
- }
+static int runtime_expand_flags;
- source_runtime(arg, flags);
+/// Set the completion context for the :runtime command.
+void set_context_in_runtime_cmd(expand_T *xp, const char *arg)
+{
+ char *p = skiptowhite(arg);
+ runtime_expand_flags
+ = *p != NUL ? get_runtime_cmd_flags((char **)&arg, (size_t)(p - arg)) : 0;
+ xp->xp_context = EXPAND_RUNTIME;
+ xp->xp_pattern = (char *)arg;
}
static void source_callback(char *fname, void *cookie)
@@ -822,12 +849,14 @@ static void source_all_matches(char *pat)
int num_files;
char **files;
- if (gen_expand_wildcards(1, &pat, &num_files, &files, EW_FILE) == OK) {
- for (int i = 0; i < num_files; i++) {
- (void)do_source(files[i], false, DOSO_NONE);
- }
- FreeWild(num_files, files);
+ if (gen_expand_wildcards(1, &pat, &num_files, &files, EW_FILE) != OK) {
+ return;
+ }
+
+ for (int i = 0; i < num_files; i++) {
+ (void)do_source(files[i], false, DOSO_NONE);
}
+ FreeWild(num_files, files);
}
/// Add the package directory to 'runtimepath'
@@ -1174,124 +1203,154 @@ void ex_packadd(exarg_T *eap)
}
}
-/// Expand color scheme, compiler or filetype names.
-/// Search from 'runtimepath':
-/// 'runtimepath'/{dirnames}/{pat}.vim
-/// When "flags" has DIP_START: search also from 'start' of 'packpath':
-/// 'packpath'/pack/ * /start/ * /{dirnames}/{pat}.vim
-/// When "flags" has DIP_OPT: search also from 'opt' of 'packpath':
-/// 'packpath'/pack/ * /opt/ * /{dirnames}/{pat}.vim
-/// When "flags" has DIP_LUA: search also performed for .lua files
-/// "dirnames" is an array with one or more directory names.
-int ExpandRTDir(char *pat, int flags, int *num_file, char ***file, char *dirnames[])
+static void ExpandRTDir_int(char *pat, size_t pat_len, int flags, bool keep_ext, garray_T *gap,
+ char *dirnames[])
{
- *num_file = 0;
- *file = NULL;
- size_t pat_len = strlen(pat);
-
- garray_T ga;
- ga_init(&ga, (int)sizeof(char *), 10);
-
- // TODO(bfredl): this is bullshit, exandpath should not reinvent path logic.
+ // TODO(bfredl): this is bullshit, expandpath should not reinvent path logic.
for (int i = 0; dirnames[i] != NULL; i++) {
- size_t size = strlen(dirnames[i]) + pat_len + 7;
- char *s = xmalloc(size);
- snprintf(s, size, "%s/%s*.vim", dirnames[i], pat);
- globpath(p_rtp, s, &ga, 0);
- if (flags & DIP_LUA) {
- snprintf(s, size, "%s/%s*.lua", dirnames[i], pat);
- globpath(p_rtp, s, &ga, 0);
+ const size_t buf_len = strlen(dirnames[i]) + pat_len + 31;
+ char *const buf = xmalloc(buf_len);
+ char *const tail = buf + 15;
+ const size_t tail_buflen = buf_len - 15;
+ int glob_flags = 0;
+ bool expand_dirs = false;
+
+ if (*dirnames[i] == NUL) { // empty dir used for :runtime
+ snprintf(tail, tail_buflen, "%s*.\\(vim\\|lua\\)", pat);
+ } else {
+ snprintf(tail, tail_buflen, "%s/%s*.\\(vim\\|lua\\)", dirnames[i], pat);
}
- xfree(s);
- }
- if (flags & DIP_START) {
- for (int i = 0; dirnames[i] != NULL; i++) {
- size_t size = strlen(dirnames[i]) + pat_len + 22;
- char *s = xmalloc(size);
- snprintf(s, size, "pack/*/start/*/%s/%s*.vim", dirnames[i], pat); // NOLINT
- globpath(p_pp, s, &ga, 0);
- if (flags & DIP_LUA) {
- snprintf(s, size, "pack/*/start/*/%s/%s*.lua", dirnames[i], pat); // NOLINT
- globpath(p_pp, s, &ga, 0);
- }
- xfree(s);
+expand:
+ if ((flags & DIP_NORTP) == 0) {
+ globpath(p_rtp, tail, gap, glob_flags, expand_dirs);
}
- for (int i = 0; dirnames[i] != NULL; i++) {
- size_t size = strlen(dirnames[i]) + pat_len + 22;
- char *s = xmalloc(size);
- snprintf(s, size, "start/*/%s/%s*.vim", dirnames[i], pat); // NOLINT
- globpath(p_pp, s, &ga, 0);
- if (flags & DIP_LUA) {
- snprintf(s, size, "start/*/%s/%s*.lua", dirnames[i], pat); // NOLINT
- globpath(p_pp, s, &ga, 0);
- }
- xfree(s);
+ if (flags & DIP_START) {
+ memcpy(tail - 15, "pack/*/start/*/", 15); // NOLINT
+ globpath(p_pp, tail - 15, gap, glob_flags, expand_dirs);
+ memcpy(tail - 8, "start/*/", 8); // NOLINT
+ globpath(p_pp, tail - 8, gap, glob_flags, expand_dirs);
}
- }
- if (flags & DIP_OPT) {
- for (int i = 0; dirnames[i] != NULL; i++) {
- size_t size = strlen(dirnames[i]) + pat_len + 20;
- char *s = xmalloc(size);
- snprintf(s, size, "pack/*/opt/*/%s/%s*.vim", dirnames[i], pat); // NOLINT
- globpath(p_pp, s, &ga, 0);
- if (flags & DIP_LUA) {
- snprintf(s, size, "pack/*/opt/*/%s/%s*.lua", dirnames[i], pat); // NOLINT
- globpath(p_pp, s, &ga, 0);
- }
- xfree(s);
+ if (flags & DIP_OPT) {
+ memcpy(tail - 13, "pack/*/opt/*/", 13); // NOLINT
+ globpath(p_pp, tail - 13, gap, glob_flags, expand_dirs);
+ memcpy(tail - 6, "opt/*/", 6); // NOLINT
+ globpath(p_pp, tail - 6, gap, glob_flags, expand_dirs);
}
- for (int i = 0; dirnames[i] != NULL; i++) {
- size_t size = strlen(dirnames[i]) + pat_len + 20;
- char *s = xmalloc(size);
- snprintf(s, size, "opt/*/%s/%s*.vim", dirnames[i], pat); // NOLINT
- globpath(p_pp, s, &ga, 0);
- if (flags & DIP_LUA) {
- snprintf(s, size, "opt/*/%s/%s*.lua", dirnames[i], pat); // NOLINT
- globpath(p_pp, s, &ga, 0);
- }
- xfree(s);
+ if (*dirnames[i] == NUL && !expand_dirs) {
+ // expand dir names in another round
+ snprintf(tail, tail_buflen, "%s*", pat);
+ glob_flags = WILD_ADD_SLASH;
+ expand_dirs = true;
+ goto expand;
+ }
+
+ xfree(buf);
+ }
+
+ int pat_pathsep_cnt = 0;
+ for (size_t i = 0; i < pat_len; i++) {
+ if (vim_ispathsep(pat[i])) {
+ pat_pathsep_cnt++;
}
}
- for (int i = 0; i < ga.ga_len; i++) {
- char *match = ((char **)ga.ga_data)[i];
+ for (int i = 0; i < gap->ga_len; i++) {
+ char *match = ((char **)gap->ga_data)[i];
char *s = match;
char *e = s + strlen(s);
- if (e - s > 4 && (STRNICMP(e - 4, ".vim", 4) == 0
- || ((flags & DIP_LUA)
- && STRNICMP(e - 4, ".lua", 4) == 0))) {
+ if (e - s > 4 && !keep_ext && (STRNICMP(e - 4, ".vim", 4) == 0
+ || STRNICMP(e - 4, ".lua", 4) == 0)) {
e -= 4;
- for (s = e; s > match; MB_PTR_BACK(match, s)) {
- if (vim_ispathsep(*s)) {
- break;
- }
- }
- s++;
*e = NUL;
+ }
+
+ int match_pathsep_cnt = (e > s && e[-1] == '/') ? -1 : 0;
+ for (s = e; s > match; MB_PTR_BACK(match, s)) {
+ if (vim_ispathsep(*s) && ++match_pathsep_cnt > pat_pathsep_cnt) {
+ break;
+ }
+ }
+ s++;
+ if (s != match) {
assert((e - s) + 1 >= 0);
memmove(match, s, (size_t)(e - s) + 1);
}
}
- if (GA_EMPTY(&ga)) {
- return FAIL;
+ if (GA_EMPTY(gap)) {
+ return;
}
// Sort and remove duplicates which can happen when specifying multiple
// directories in dirnames.
- ga_remove_duplicate_strings(&ga);
+ ga_remove_duplicate_strings(gap);
+}
+
+/// Expand color scheme, compiler or filetype names.
+/// Search from 'runtimepath':
+/// 'runtimepath'/{dirnames}/{pat}.(vim|lua)
+/// When "flags" has DIP_START: search also from "start" of 'packpath':
+/// 'packpath'/pack/*/start/*/{dirnames}/{pat}.(vim|lua)
+/// When "flags" has DIP_OPT: search also from "opt" of 'packpath':
+/// 'packpath'/pack/*/opt/*/{dirnames}/{pat}.(vim|lua)
+/// "dirnames" is an array with one or more directory names.
+int ExpandRTDir(char *pat, int flags, int *num_file, char ***file, char *dirnames[])
+{
+ *num_file = 0;
+ *file = NULL;
+
+ garray_T ga;
+ ga_init(&ga, (int)sizeof(char *), 10);
+
+ ExpandRTDir_int(pat, strlen(pat), flags, false, &ga, dirnames);
+
+ if (GA_EMPTY(&ga)) {
+ return FAIL;
+ }
*file = ga.ga_data;
*num_file = ga.ga_len;
return OK;
}
+/// Handle command line completion for :runtime command.
+int expand_runtime_cmd(char *pat, int *numMatches, char ***matches)
+{
+ *numMatches = 0;
+ *matches = NULL;
+
+ garray_T ga;
+ ga_init(&ga, sizeof(char *), 10);
+
+ const size_t pat_len = strlen(pat);
+ char *dirnames[] = { "", NULL };
+ ExpandRTDir_int(pat, pat_len, runtime_expand_flags, true, &ga, dirnames);
+
+ // Try to complete values for [where] argument when none was found.
+ if (runtime_expand_flags == 0) {
+ char *where_values[] = { "START", "OPT", "PACK", "ALL" };
+ for (size_t i = 0; i < ARRAY_SIZE(where_values); i++) {
+ if (strncmp(pat, where_values[i], pat_len) == 0) {
+ GA_APPEND(char *, &ga, xstrdup(where_values[i]));
+ }
+ }
+ }
+
+ if (GA_EMPTY(&ga)) {
+ return FAIL;
+ }
+
+ *matches = ga.ga_data;
+ *numMatches = ga.ga_len;
+ return OK;
+}
+
/// Expand loadplugin names:
-/// 'packpath'/pack/ * /opt/{pat}
+/// 'packpath'/pack/*/opt/{pat}
int ExpandPackAddDir(char *pat, int *num_file, char ***file)
{
garray_T ga;
@@ -1304,9 +1363,9 @@ int ExpandPackAddDir(char *pat, int *num_file, char ***file)
size_t buflen = pat_len + 26;
char *s = xmalloc(buflen);
snprintf(s, buflen, "pack/*/opt/%s*", pat); // NOLINT
- globpath(p_pp, s, &ga, 0);
+ globpath(p_pp, s, &ga, 0, true);
snprintf(s, buflen, "opt/%s*", pat); // NOLINT
- globpath(p_pp, s, &ga, 0);
+ globpath(p_pp, s, &ga, 0, true);
xfree(s);
for (int i = 0; i < ga.ga_len; i++) {
@@ -2161,12 +2220,17 @@ scriptitem_T *get_current_script_id(char **fnamep, sctx_T *ret_sctx)
/// ":scriptnames"
void ex_scriptnames(exarg_T *eap)
{
- if (eap->addr_count > 0) {
+ if (eap->addr_count > 0 || *eap->arg != NUL) {
// :script {scriptId}: edit the script
- if (eap->line2 < 1 || eap->line2 > script_items.ga_len) {
+ if (eap->addr_count > 0 && !SCRIPT_ID_VALID(eap->line2)) {
emsg(_(e_invarg));
} else {
- eap->arg = SCRIPT_ITEM(eap->line2).sn_name;
+ if (eap->addr_count > 0) {
+ eap->arg = SCRIPT_ITEM(eap->line2).sn_name;
+ } else {
+ expand_env(eap->arg, NameBuff, MAXPATHL);
+ eap->arg = NameBuff;
+ }
do_exedit(eap, NULL);
}
return;
diff --git a/src/nvim/runtime.h b/src/nvim/runtime.h
index de363020f8..97063b900c 100644
--- a/src/nvim/runtime.h
+++ b/src/nvim/runtime.h
@@ -105,7 +105,6 @@ typedef kvec_t(char *) CharVec;
#define DIP_NORTP 0x20 // do not use 'runtimepath'
#define DIP_NOAFTER 0x40 // skip "after" directories
#define DIP_AFTER 0x80 // only use "after" directories
-#define DIP_LUA 0x100 // also use ".lua" files
#define DIP_DIRFILE 0x200 // find both files and directories
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index b18bf7ed6a..05da6e0ef1 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -295,52 +295,54 @@ bool get_keymap_str(win_T *wp, char *fmt, char *buf, int len)
return false;
}
- {
- buf_T *old_curbuf = curbuf;
- win_T *old_curwin = curwin;
- char *s;
-
- curbuf = wp->w_buffer;
- curwin = wp;
- STRCPY(buf, "b:keymap_name"); // must be writable
- emsg_skip++;
- s = p = eval_to_string(buf, NULL, false);
- emsg_skip--;
- curbuf = old_curbuf;
- curwin = old_curwin;
- if (p == NULL || *p == NUL) {
- if (wp->w_buffer->b_kmap_state & KEYMAP_LOADED) {
- p = wp->w_buffer->b_p_keymap;
- } else {
- p = "lang";
- }
- }
- if (vim_snprintf(buf, (size_t)len, fmt, p) > len - 1) {
- buf[0] = NUL;
+ buf_T *old_curbuf = curbuf;
+ win_T *old_curwin = curwin;
+ char *s;
+
+ curbuf = wp->w_buffer;
+ curwin = wp;
+ STRCPY(buf, "b:keymap_name"); // must be writable
+ emsg_skip++;
+ s = p = eval_to_string(buf, NULL, false);
+ emsg_skip--;
+ curbuf = old_curbuf;
+ curwin = old_curwin;
+ if (p == NULL || *p == NUL) {
+ if (wp->w_buffer->b_kmap_state & KEYMAP_LOADED) {
+ p = wp->w_buffer->b_p_keymap;
+ } else {
+ p = "lang";
}
- xfree(s);
}
+ if (vim_snprintf(buf, (size_t)len, fmt, p) > len - 1) {
+ buf[0] = NUL;
+ }
+ xfree(s);
return buf[0] != NUL;
}
/// Prepare for 'hlsearch' highlighting.
void start_search_hl(void)
{
- if (p_hls && !no_hlsearch) {
- end_search_hl(); // just in case it wasn't called before
- last_pat_prog(&screen_search_hl.rm);
- // Set the time limit to 'redrawtime'.
- screen_search_hl.tm = profile_setlimit(p_rdt);
+ if (!p_hls || no_hlsearch) {
+ return;
}
+
+ end_search_hl(); // just in case it wasn't called before
+ last_pat_prog(&screen_search_hl.rm);
+ // Set the time limit to 'redrawtime'.
+ screen_search_hl.tm = profile_setlimit(p_rdt);
}
/// Clean up for 'hlsearch' highlighting.
void end_search_hl(void)
{
- if (screen_search_hl.rm.regprog != NULL) {
- vim_regfree(screen_search_hl.rm.regprog);
- screen_search_hl.rm.regprog = NULL;
+ if (screen_search_hl.rm.regprog == NULL) {
+ return;
}
+
+ vim_regfree(screen_search_hl.rm.regprog);
+ screen_search_hl.rm.regprog = NULL;
}
/// Check if there should be a delay. Used before clearing or redrawing the
@@ -671,11 +673,13 @@ void clearmode(void)
static void recording_mode(int attr)
{
msg_puts_attr(_("recording"), attr);
- if (!shortmess(SHM_RECORDING)) {
- char s[4];
- snprintf(s, ARRAY_SIZE(s), " @%c", reg_recording);
- msg_puts_attr(s, attr);
+ if (shortmess(SHM_RECORDING)) {
+ return;
}
+
+ char s[4];
+ snprintf(s, ARRAY_SIZE(s), " @%c", reg_recording);
+ msg_puts_attr(s, attr);
}
void get_trans_bufname(buf_T *buf)
@@ -764,7 +768,6 @@ void comp_col(void)
/// Otherwise it depends on 'numberwidth' and the line count.
int number_width(win_T *wp)
{
- int n;
linenr_T lnum;
if (wp->w_p_rnu && !wp->w_p_nu) {
@@ -780,17 +783,13 @@ int number_width(win_T *wp)
}
wp->w_nrwidth_line_count = lnum;
- // make best estimate for 'statuscolumn'
+ // reset for 'statuscolumn'
if (*wp->w_p_stc != NUL) {
- char buf[MAXPATHL];
- wp->w_nrwidth_width = 0;
- n = build_statuscol_str(wp, true, false, lnum, 0, 0, NUL, buf, NULL, NULL);
- n = MAX(n, (wp->w_p_nu || wp->w_p_rnu) * (int)wp->w_p_nuw);
- wp->w_nrwidth_width = MIN(n, MAX_NUMBERWIDTH);
+ wp->w_nrwidth_width = (wp->w_p_nu || wp->w_p_rnu) * (int)wp->w_p_nuw;
return wp->w_nrwidth_width;
}
- n = 0;
+ int n = 0;
do {
lnum /= 10;
n++;
@@ -815,15 +814,15 @@ int number_width(win_T *wp)
/// Calls mb_cptr2char_adv(p) and returns the character.
/// If "p" starts with "\x", "\u" or "\U" the hex or unicode value is used.
/// Returns 0 for invalid hex or invalid UTF-8 byte.
-static int get_encoded_char_adv(const char_u **p)
+static int get_encoded_char_adv(const char **p)
{
- const char *s = (const char *)(*p);
+ const char *s = *p;
if (s[0] == '\\' && (s[1] == 'x' || s[1] == 'u' || s[1] == 'U')) {
int64_t num = 0;
for (int bytes = s[1] == 'x' ? 1 : s[1] == 'u' ? 2 : 4; bytes > 0; bytes--) {
*p += 2;
- int n = hexhex2nr((char *)(*p));
+ int n = hexhex2nr(*p);
if (n < 0) {
return 0;
}
@@ -952,7 +951,7 @@ char *set_chars_option(win_T *wp, char **varp, bool apply)
if (strncmp(p, tab[i].name, len) == 0
&& p[len] == ':'
&& p[len + 1] != NUL) {
- const char_u *s = (char_u *)p + len + 1;
+ const char *s = p + len + 1;
int c1 = get_encoded_char_adv(&s);
if (c1 == 0 || char2cells(c1) > 1) {
return e_invarg;
@@ -983,7 +982,7 @@ char *set_chars_option(win_T *wp, char **varp, bool apply)
*(tab[i].cp) = c1;
}
}
- p = (char *)s;
+ p = s;
break;
}
}
@@ -996,7 +995,7 @@ char *set_chars_option(win_T *wp, char **varp, bool apply)
&& strncmp(p, "multispace", len) == 0
&& p[len] == ':'
&& p[len + 1] != NUL) {
- const char_u *s = (char_u *)p + len + 1;
+ const char *s = p + len + 1;
if (round == 0) {
// Get length of lcs-multispace string in the first round
last_multispace = p;
@@ -1012,7 +1011,7 @@ char *set_chars_option(win_T *wp, char **varp, bool apply)
// lcs-multispace cannot be an empty string
return e_invarg;
}
- p = (char *)s;
+ p = s;
} else {
int multispace_pos = 0;
while (*s != NUL && *s != ',') {
@@ -1021,13 +1020,13 @@ char *set_chars_option(win_T *wp, char **varp, bool apply)
wp->w_p_lcs_chars.multispace[multispace_pos++] = c1;
}
}
- p = (char *)s;
+ p = s;
}
} else if (is_listchars
&& strncmp(p, "leadmultispace", len2) == 0
&& p[len2] == ':'
&& p[len2 + 1] != NUL) {
- const char_u *s = (char_u *)p + len2 + 1;
+ const char *s = p + len2 + 1;
if (round == 0) {
// get length of lcs-leadmultispace string in first round
last_lmultispace = p;
@@ -1043,7 +1042,7 @@ char *set_chars_option(win_T *wp, char **varp, bool apply)
// lcs-leadmultispace cannot be an empty string
return e_invarg;
}
- p = (char *)s;
+ p = s;
} else {
int multispace_pos = 0;
while (*s != NUL && *s != ',') {
@@ -1052,7 +1051,7 @@ char *set_chars_option(win_T *wp, char **varp, bool apply)
wp->w_p_lcs_chars.leadmultispace[multispace_pos++] = c1;
}
}
- p = (char *)s;
+ p = s;
}
} else {
return e_invarg;
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 871d2f9a0a..eb5cc2e07f 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -133,7 +133,7 @@ typedef struct SearchedFile {
/// @param regmatch return: pattern and ignore-case flag
///
/// @return FAIL if failed, OK otherwise.
-int search_regcomp(char_u *pat, char_u **used_pat, int pat_save, int pat_use, int options,
+int search_regcomp(char *pat, char **used_pat, int pat_save, int pat_use, int options,
regmmatch_T *regmatch)
{
int magic;
@@ -158,11 +158,11 @@ int search_regcomp(char_u *pat, char_u **used_pat, int pat_save, int pat_use, in
rc_did_emsg = true;
return FAIL;
}
- pat = (char_u *)spats[i].pat;
+ pat = spats[i].pat;
magic = spats[i].magic;
no_smartcase = spats[i].no_scs;
} else if (options & SEARCH_HIS) { // put new pattern in history
- add_to_history(HIST_SEARCH, (char *)pat, true, NUL);
+ add_to_history(HIST_SEARCH, pat, true, NUL);
}
if (used_pat) {
@@ -171,9 +171,9 @@ int search_regcomp(char_u *pat, char_u **used_pat, int pat_save, int pat_use, in
xfree(mr_pattern);
if (curwin->w_p_rl && *curwin->w_p_rlc == 's') {
- mr_pattern = reverse_text((char *)pat);
+ mr_pattern = reverse_text(pat);
} else {
- mr_pattern = xstrdup((char *)pat);
+ mr_pattern = xstrdup(pat);
}
// Save the currently used pattern in the appropriate place,
@@ -181,17 +181,17 @@ int search_regcomp(char_u *pat, char_u **used_pat, int pat_save, int pat_use, in
if (!(options & SEARCH_KEEP) && (cmdmod.cmod_flags & CMOD_KEEPPATTERNS) == 0) {
// search or global command
if (pat_save == RE_SEARCH || pat_save == RE_BOTH) {
- save_re_pat(RE_SEARCH, (char *)pat, magic);
+ save_re_pat(RE_SEARCH, pat, magic);
}
// substitute or global command
if (pat_save == RE_SUBST || pat_save == RE_BOTH) {
- save_re_pat(RE_SUBST, (char *)pat, magic);
+ save_re_pat(RE_SUBST, pat, magic);
}
}
- regmatch->rmm_ic = ignorecase((char *)pat);
+ regmatch->rmm_ic = ignorecase(pat);
regmatch->rmm_maxcol = 0;
- regmatch->regprog = vim_regcomp((char *)pat, magic ? RE_MAGIC : 0);
+ regmatch->regprog = vim_regcomp(pat, magic ? RE_MAGIC : 0);
if (regmatch->regprog == NULL) {
return FAIL;
}
@@ -206,20 +206,22 @@ char *get_search_pat(void)
void save_re_pat(int idx, char *pat, int magic)
{
- if (spats[idx].pat != pat) {
- free_spat(&spats[idx]);
- spats[idx].pat = xstrdup(pat);
- spats[idx].magic = magic;
- spats[idx].no_scs = no_smartcase;
- spats[idx].timestamp = os_time();
- spats[idx].additional_data = NULL;
- last_idx = idx;
- // If 'hlsearch' set and search pat changed: need redraw.
- if (p_hls) {
- redraw_all_later(UPD_SOME_VALID);
- }
- set_no_hlsearch(false);
+ if (spats[idx].pat == pat) {
+ return;
+ }
+
+ free_spat(&spats[idx]);
+ spats[idx].pat = xstrdup(pat);
+ spats[idx].magic = magic;
+ spats[idx].no_scs = no_smartcase;
+ spats[idx].timestamp = os_time();
+ spats[idx].additional_data = NULL;
+ last_idx = idx;
+ // If 'hlsearch' set and search pat changed: need redraw.
+ if (p_hls) {
+ redraw_all_later(UPD_SOME_VALID);
}
+ set_no_hlsearch(false);
}
// Save the search patterns, so they can be restored later.
@@ -228,38 +230,42 @@ static int save_level = 0;
void save_search_patterns(void)
{
- if (save_level++ == 0) {
- saved_spats[0] = spats[0];
- if (spats[0].pat != NULL) {
- saved_spats[0].pat = xstrdup(spats[0].pat);
- }
- saved_spats[1] = spats[1];
- if (spats[1].pat != NULL) {
- saved_spats[1].pat = xstrdup(spats[1].pat);
- }
- if (mr_pattern == NULL) {
- saved_mr_pattern = NULL;
- } else {
- saved_mr_pattern = xstrdup(mr_pattern);
- }
- saved_spats_last_idx = last_idx;
- saved_spats_no_hlsearch = no_hlsearch;
+ if (save_level++ != 0) {
+ return;
+ }
+
+ saved_spats[0] = spats[0];
+ if (spats[0].pat != NULL) {
+ saved_spats[0].pat = xstrdup(spats[0].pat);
+ }
+ saved_spats[1] = spats[1];
+ if (spats[1].pat != NULL) {
+ saved_spats[1].pat = xstrdup(spats[1].pat);
}
+ if (mr_pattern == NULL) {
+ saved_mr_pattern = NULL;
+ } else {
+ saved_mr_pattern = xstrdup(mr_pattern);
+ }
+ saved_spats_last_idx = last_idx;
+ saved_spats_no_hlsearch = no_hlsearch;
}
void restore_search_patterns(void)
{
- if (--save_level == 0) {
- free_spat(&spats[0]);
- spats[0] = saved_spats[0];
- set_vv_searchforward();
- free_spat(&spats[1]);
- spats[1] = saved_spats[1];
- xfree(mr_pattern);
- mr_pattern = saved_mr_pattern;
- last_idx = saved_spats_last_idx;
- set_no_hlsearch(saved_spats_no_hlsearch);
+ if (--save_level != 0) {
+ return;
}
+
+ free_spat(&spats[0]);
+ spats[0] = saved_spats[0];
+ set_vv_searchforward();
+ free_spat(&spats[1]);
+ spats[1] = saved_spats[1];
+ xfree(mr_pattern);
+ mr_pattern = saved_mr_pattern;
+ last_idx = saved_spats_last_idx;
+ set_no_hlsearch(saved_spats_no_hlsearch);
}
static inline void free_spat(struct spat *const spat)
@@ -346,9 +352,9 @@ static void restore_incsearch_state(void)
search_match_lines = saved_search_match_lines;
}
-char_u *last_search_pattern(void)
+char *last_search_pattern(void)
{
- return (char_u *)spats[RE_SEARCH].pat;
+ return spats[RE_SEARCH].pat;
}
/// Return true when case should be ignored for search pattern "pat".
@@ -365,7 +371,7 @@ int ignorecase_opt(char *pat, int ic_in, int scs)
if (ic && !no_smartcase && scs
&& !(ctrl_x_mode_not_default()
&& curbuf->b_p_inf)) {
- ic = !pat_has_uppercase((char_u *)pat);
+ ic = !pat_has_uppercase(pat);
}
no_smartcase = false;
@@ -373,14 +379,14 @@ int ignorecase_opt(char *pat, int ic_in, int scs)
}
/// Returns true if pattern `pat` has an uppercase character.
-bool pat_has_uppercase(char_u *pat)
+bool pat_has_uppercase(char *pat)
FUNC_ATTR_NONNULL_ALL
{
- char *p = (char *)pat;
+ char *p = pat;
magic_T magic_val = MAGIC_ON;
// get the magicness of the pattern
- (void)skip_regexp_ex((char *)pat, NUL, magic_isset(), NULL, NULL, &magic_val);
+ (void)skip_regexp_ex(pat, NUL, magic_isset(), NULL, NULL, &magic_val);
while (*p != NUL) {
const int l = utfc_ptr2len(p);
@@ -431,7 +437,7 @@ int last_csearch_until(void)
return last_t_cmd == true;
}
-void set_last_csearch(int c, char_u *s, int len)
+void set_last_csearch(int c, char *s, int len)
{
*lastc = (char_u)c;
lastc_bytelen = len;
@@ -452,9 +458,9 @@ void set_csearch_until(int t_cmd)
last_t_cmd = t_cmd;
}
-char_u *last_search_pat(void)
+char *last_search_pat(void)
{
- return (char_u *)spats[last_idx].pat;
+ return spats[last_idx].pat;
}
// Reset search direction to forward. For "gd" and "gD" commands.
@@ -466,14 +472,14 @@ void reset_search_dir(void)
// Set the last search pattern. For ":let @/ =" and ShaDa file.
// Also set the saved search pattern, so that this works in an autocommand.
-void set_last_search_pat(const char_u *s, int idx, int magic, int setlast)
+void set_last_search_pat(const char *s, int idx, int magic, int setlast)
{
free_spat(&spats[idx]);
// An empty string means that nothing should be matched.
if (*s == NUL) {
spats[idx].pat = NULL;
} else {
- spats[idx].pat = xstrdup((char *)s);
+ spats[idx].pat = xstrdup(s);
}
spats[idx].timestamp = os_time();
spats[idx].additional_data = NULL;
@@ -513,7 +519,7 @@ void last_pat_prog(regmmatch_T *regmatch)
return;
}
emsg_off++; // So it doesn't beep if bad expr
- (void)search_regcomp((char_u *)"", NULL, 0, last_idx, SEARCH_KEEP, regmatch);
+ (void)search_regcomp("", NULL, 0, last_idx, SEARCH_KEEP, regmatch);
emsg_off--;
}
@@ -540,7 +546,7 @@ void last_pat_prog(regmmatch_T *regmatch)
/// @returns FAIL (zero) for failure, non-zero for success.
/// the index of the first matching
/// subpattern plus one; one if there was none.
-int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir, char_u *pat,
+int searchit(win_T *win, buf_T *buf, pos_T *pos, pos_T *end_pos, Direction dir, char *pat,
long count, int options, int pat_use, searchit_arg_T *extra_arg)
{
int found;
@@ -1296,7 +1302,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, long count, i
}
c = searchit(curwin, curbuf, &pos, NULL, dirc == '/' ? FORWARD : BACKWARD,
- (char_u *)searchstr, count,
+ searchstr, count,
(spats[0].off.end * SEARCH_END
+ (options
& (SEARCH_KEEP + SEARCH_PEEK + SEARCH_HIS + SEARCH_MSG
@@ -2321,55 +2327,63 @@ void showmatch(int c)
if ((lpos = findmatch(NULL, NUL)) == NULL) { // no match, so beep
vim_beep(BO_MATCH);
- } else if (lpos->lnum >= curwin->w_topline
- && lpos->lnum < curwin->w_botline) {
- if (!curwin->w_p_wrap) {
- getvcol(curwin, lpos, NULL, &vcol, NULL);
- }
- if (curwin->w_p_wrap
- || (vcol >= curwin->w_leftcol
- && vcol < curwin->w_leftcol + curwin->w_width_inner)) {
- mpos = *lpos; // save the pos, update_screen() may change it
- save_cursor = curwin->w_cursor;
- save_so = *so;
- save_siso = *siso;
- // Handle "$" in 'cpo': If the ')' is typed on top of the "$",
- // stop displaying the "$".
- if (dollar_vcol >= 0 && dollar_vcol == curwin->w_virtcol) {
- dollar_vcol = -1;
- }
- curwin->w_virtcol++; // do display ')' just before "$"
- update_screen(); // show the new char first
-
- save_dollar_vcol = dollar_vcol;
- save_state = State;
- State = MODE_SHOWMATCH;
- ui_cursor_shape(); // may show different cursor shape
- curwin->w_cursor = mpos; // move to matching char
- *so = 0; // don't use 'scrolloff' here
- *siso = 0; // don't use 'sidescrolloff' here
- show_cursor_info(false);
- setcursor();
- ui_flush();
- // Restore dollar_vcol(), because setcursor() may call curs_rows()
- // which resets it if the matching position is in a previous line
- // and has a higher column number.
- dollar_vcol = save_dollar_vcol;
-
- // brief pause, unless 'm' is present in 'cpo' and a character is
- // available.
- if (vim_strchr(p_cpo, CPO_SHOWMATCH) != NULL) {
- os_delay((uint64_t)p_mat * 100L + 8, true);
- } else if (!char_avail()) {
- os_delay((uint64_t)p_mat * 100L + 9, false);
- }
- curwin->w_cursor = save_cursor; // restore cursor position
- *so = save_so;
- *siso = save_siso;
- State = save_state;
- ui_cursor_shape(); // may show different cursor shape
- }
+ return;
+ }
+
+ if (lpos->lnum < curwin->w_topline || lpos->lnum >= curwin->w_botline) {
+ return;
+ }
+
+ if (!curwin->w_p_wrap) {
+ getvcol(curwin, lpos, NULL, &vcol, NULL);
+ }
+
+ bool col_visible = curwin->w_p_wrap
+ || (vcol >= curwin->w_leftcol
+ && vcol < curwin->w_leftcol + curwin->w_width_inner);
+ if (!col_visible) {
+ return;
+ }
+
+ mpos = *lpos; // save the pos, update_screen() may change it
+ save_cursor = curwin->w_cursor;
+ save_so = *so;
+ save_siso = *siso;
+ // Handle "$" in 'cpo': If the ')' is typed on top of the "$",
+ // stop displaying the "$".
+ if (dollar_vcol >= 0 && dollar_vcol == curwin->w_virtcol) {
+ dollar_vcol = -1;
}
+ curwin->w_virtcol++; // do display ')' just before "$"
+ update_screen(); // show the new char first
+
+ save_dollar_vcol = dollar_vcol;
+ save_state = State;
+ State = MODE_SHOWMATCH;
+ ui_cursor_shape(); // may show different cursor shape
+ curwin->w_cursor = mpos; // move to matching char
+ *so = 0; // don't use 'scrolloff' here
+ *siso = 0; // don't use 'sidescrolloff' here
+ show_cursor_info(false);
+ setcursor();
+ ui_flush();
+ // Restore dollar_vcol(), because setcursor() may call curs_rows()
+ // which resets it if the matching position is in a previous line
+ // and has a higher column number.
+ dollar_vcol = save_dollar_vcol;
+
+ // brief pause, unless 'm' is present in 'cpo' and a character is
+ // available.
+ if (vim_strchr(p_cpo, CPO_SHOWMATCH) != NULL) {
+ os_delay((uint64_t)p_mat * 100L + 8, true);
+ } else if (!char_avail()) {
+ os_delay((uint64_t)p_mat * 100L + 9, false);
+ }
+ curwin->w_cursor = save_cursor; // restore cursor position
+ *so = save_so;
+ *siso = save_siso;
+ State = save_state;
+ ui_cursor_shape(); // may show different cursor shape
}
/// Find next search match under cursor, cursor at end.
@@ -2440,7 +2454,7 @@ int current_search(long count, bool forward)
result = searchit(curwin, curbuf, &pos, &end_pos,
(dir ? FORWARD : BACKWARD),
- (char_u *)spats[last_idx].pat, i ? count : 1,
+ spats[last_idx].pat, i ? count : 1,
SEARCH_KEEP | flags, RE_SEARCH, NULL);
p_ws = old_p_ws;
@@ -2527,7 +2541,7 @@ static int is_zero_width(char *pattern, int move, pos_T *cur, Direction directio
pattern = spats[last_idx].pat;
}
- if (search_regcomp((char_u *)pattern, NULL, RE_SEARCH, RE_SEARCH,
+ if (search_regcomp(pattern, NULL, RE_SEARCH, RE_SEARCH,
SEARCH_KEEP, &regmatch) == FAIL) {
return -1;
}
@@ -2542,7 +2556,7 @@ static int is_zero_width(char *pattern, int move, pos_T *cur, Direction directio
// accept a match at the cursor position
flag = SEARCH_START;
}
- if (searchit(curwin, curbuf, &pos, NULL, direction, (char_u *)pattern, 1,
+ if (searchit(curwin, curbuf, &pos, NULL, direction, pattern, 1,
SEARCH_KEEP + flag, RE_SEARCH, NULL) != FAIL) {
// Zero-width pattern should match somewhere, then we can check if
// start and end are in the same position.
@@ -2588,56 +2602,63 @@ static void cmdline_search_stat(int dirc, pos_T *pos, pos_T *cursor_pos, bool sh
update_search_stat(dirc, pos, cursor_pos, &stat, recompute, maxcount,
timeout);
- if (stat.cur > 0) {
- char t[SEARCH_STAT_BUF_LEN];
-
- if (curwin->w_p_rl && *curwin->w_p_rlc == 's') {
- if (stat.incomplete == 1) {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[?/??]");
- } else if (stat.cnt > maxcount && stat.cur > maxcount) {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>%d/>%d]",
- maxcount, maxcount);
- } else if (stat.cnt > maxcount) {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>%d/%d]",
- maxcount, stat.cur);
- } else {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/%d]",
- stat.cnt, stat.cur);
- }
+ if (stat.cur <= 0) {
+ return;
+ }
+
+ char t[SEARCH_STAT_BUF_LEN];
+
+ if (curwin->w_p_rl && *curwin->w_p_rlc == 's') {
+ if (stat.incomplete == 1) {
+ vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[?/??]");
+ } else if (stat.cnt > maxcount && stat.cur > maxcount) {
+ vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>%d/>%d]",
+ maxcount, maxcount);
+ } else if (stat.cnt > maxcount) {
+ vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>%d/%d]",
+ maxcount, stat.cur);
} else {
- if (stat.incomplete == 1) {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[?/??]");
- } else if (stat.cnt > maxcount && stat.cur > maxcount) {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>%d/>%d]",
- maxcount, maxcount);
- } else if (stat.cnt > maxcount) {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/>%d]",
- stat.cur, maxcount);
- } else {
- vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/%d]",
- stat.cur, stat.cnt);
- }
+ vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/%d]",
+ stat.cnt, stat.cur);
}
-
- size_t len = strlen(t);
- if (show_top_bot_msg && len + 2 < SEARCH_STAT_BUF_LEN) {
- memmove(t + 2, t, len);
- t[0] = 'W';
- t[1] = ' ';
- len += 2;
+ } else {
+ if (stat.incomplete == 1) {
+ vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[?/??]");
+ } else if (stat.cnt > maxcount && stat.cur > maxcount) {
+ vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[>%d/>%d]",
+ maxcount, maxcount);
+ } else if (stat.cnt > maxcount) {
+ vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/>%d]",
+ stat.cur, maxcount);
+ } else {
+ vim_snprintf(t, SEARCH_STAT_BUF_LEN, "[%d/%d]",
+ stat.cur, stat.cnt);
}
+ }
- memmove(msgbuf + strlen(msgbuf) - len, t, len);
- if (dirc == '?' && stat.cur == maxcount + 1) {
- stat.cur = -1;
- }
+ size_t len = strlen(t);
+ if (show_top_bot_msg && len + 2 < SEARCH_STAT_BUF_LEN) {
+ memmove(t + 2, t, len);
+ t[0] = 'W';
+ t[1] = ' ';
+ len += 2;
+ }
+
+ size_t msgbuf_len = strlen(msgbuf);
+ if (len > msgbuf_len) {
+ len = msgbuf_len;
+ }
+ memmove(msgbuf + msgbuf_len - len, t, len);
- // keep the message even after redraw, but don't put in history
- msg_hist_off = true;
- msg_ext_set_kind("search_count");
- give_warning(msgbuf, false);
- msg_hist_off = false;
+ if (dirc == '?' && stat.cur == maxcount + 1) {
+ stat.cur = -1;
}
+
+ // keep the message even after redraw, but don't put in history
+ msg_hist_off = true;
+ msg_ext_set_kind("search_count");
+ give_warning(msgbuf, false);
+ msg_hist_off = false;
}
// Add the search count information to "stat".
@@ -2942,7 +2963,7 @@ typedef struct {
#define FUZZY_MATCH_RECURSION_LIMIT 10
/// Compute a score for a fuzzy matched string. The matching character locations
-/// are in 'matches'.
+/// are in "matches".
static int fuzzy_match_compute_score(const char *const str, const int strSz,
const uint32_t *const matches, const int numMatches)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
@@ -3007,7 +3028,7 @@ static int fuzzy_match_compute_score(const char *const str, const int strSz,
return score;
}
-/// Perform a recursive search for fuzzy matching 'fuzpat' in 'str'.
+/// Perform a recursive search for fuzzy matching "fuzpat" in "str".
/// @return the number of matching characters.
static int fuzzy_match_recursive(const char *fuzpat, const char *str, uint32_t strIdx,
int *const outScore, const char *const strBegin, const int strLen,
@@ -3107,23 +3128,23 @@ static int fuzzy_match_recursive(const char *fuzpat, const char *str, uint32_t s
/// Uses char_u for match indices. Therefore patterns are limited to
/// MAX_FUZZY_MATCHES characters.
///
-/// @return true if 'pat_arg' matches 'str'. Also returns the match score in
-/// 'outScore' and the matching character positions in 'matches'.
-bool fuzzy_match(char_u *const str, const char_u *const pat_arg, const bool matchseq,
+/// @return true if "pat_arg" matches "str". Also returns the match score in
+/// "outScore" and the matching character positions in "matches".
+bool fuzzy_match(char *const str, const char *const pat_arg, const bool matchseq,
int *const outScore, uint32_t *const matches, const int maxMatches)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+ FUNC_ATTR_NONNULL_ALL
{
- const int len = mb_charlen((char *)str);
+ const int len = mb_charlen(str);
bool complete = false;
int numMatches = 0;
*outScore = 0;
- char *const save_pat = xstrdup((char *)pat_arg);
+ char *const save_pat = xstrdup(pat_arg);
char *pat = save_pat;
char *p = pat;
- // Try matching each word in 'pat_arg' in 'str'
+ // Try matching each word in "pat_arg" in "str"
while (true) {
if (matchseq) {
complete = true;
@@ -3146,7 +3167,7 @@ bool fuzzy_match(char_u *const str, const char_u *const pat_arg, const bool matc
int score = 0;
int recursionCount = 0;
const int matchCount
- = fuzzy_match_recursive(pat, (char *)str, 0, &score, (char *)str, len, NULL,
+ = fuzzy_match_recursive(pat, str, 0, &score, str, len, NULL,
matches + numMatches,
maxMatches - numMatches, 0, &recursionCount);
if (matchCount == 0) {
@@ -3183,14 +3204,14 @@ static int fuzzy_match_item_compare(const void *const s1, const void *const s2)
return v1 == v2 ? (idx1 - idx2) : v1 > v2 ? -1 : 1;
}
-/// Fuzzy search the string 'str' in a list of 'items' and return the matching
-/// strings in 'fmatchlist'.
-/// If 'matchseq' is true, then for multi-word search strings, match all the
+/// Fuzzy search the string "str" in a list of "items" and return the matching
+/// strings in "fmatchlist".
+/// If "matchseq" is true, then for multi-word search strings, match all the
/// words in sequence.
-/// If 'items' is a list of strings, then search for 'str' in the list.
-/// If 'items' is a list of dicts, then either use 'key' to lookup the string
-/// for each item or use 'item_cb' Funcref function to get the string.
-/// If 'retmatchpos' is true, then return a list of positions where 'str'
+/// If "items" is a list of strings, then search for "str" in the list.
+/// If "items" is a list of dicts, then either use "key" to lookup the string
+/// for each item or use "item_cb" Funcref function to get the string.
+/// If "retmatchpos" is true, then return a list of positions where "str"
/// matches for each item.
static void fuzzy_match_in_list(list_T *const l, char *const str, const bool matchseq,
const char *const key, Callback *const item_cb,
@@ -3245,14 +3266,14 @@ static void fuzzy_match_in_list(list_T *const l, char *const str, const bool mat
}
int score;
- if (itemstr != NULL && fuzzy_match((char_u *)itemstr, (char_u *)str, matchseq, &score, matches,
+ if (itemstr != NULL && fuzzy_match(itemstr, str, matchseq, &score, matches,
MAX_FUZZY_MATCHES)) {
items[match_count].idx = (int)match_count;
items[match_count].item = li;
items[match_count].score = score;
// Copy the list of matching positions in itemstr to a list, if
- // 'retmatchpos' is set.
+ // "retmatchpos" is set.
if (retmatchpos) {
items[match_count].lmatchpos = tv_list_alloc(kListLenMayKnow);
int j = 0;
@@ -3326,8 +3347,8 @@ static void fuzzy_match_in_list(list_T *const l, char *const str, const bool mat
xfree(items);
}
-/// Do fuzzy matching. Returns the list of matched strings in 'rettv'.
-/// If 'retmatchpos' is true, also returns the matching character positions.
+/// Do fuzzy matching. Returns the list of matched strings in "rettv".
+/// If "retmatchpos" is true, also returns the matching character positions.
static void do_fuzzymatch(const typval_T *const argvars, typval_T *const rettv,
const bool retmatchpos)
FUNC_ATTR_NONNULL_ALL
@@ -3411,6 +3432,109 @@ void f_matchfuzzypos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
do_fuzzymatch(argvars, rettv, true);
}
+/// Same as fuzzy_match_item_compare() except for use with a string match
+static int fuzzy_match_str_compare(const void *const s1, const void *const s2)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
+{
+ const int v1 = ((fuzmatch_str_T *)s1)->score;
+ const int v2 = ((fuzmatch_str_T *)s2)->score;
+ const int idx1 = ((fuzmatch_str_T *)s1)->idx;
+ const int idx2 = ((fuzmatch_str_T *)s2)->idx;
+
+ return v1 == v2 ? (idx1 - idx2) : v1 > v2 ? -1 : 1;
+}
+
+/// Sort fuzzy matches by score
+static void fuzzy_match_str_sort(fuzmatch_str_T *const fm, const int sz)
+ FUNC_ATTR_NONNULL_ALL
+{
+ // Sort the list by the descending order of the match score
+ qsort(fm, (size_t)sz, sizeof(fuzmatch_str_T), fuzzy_match_str_compare);
+}
+
+/// Same as fuzzy_match_item_compare() except for use with a function name
+/// string match. <SNR> functions should be sorted to the end.
+static int fuzzy_match_func_compare(const void *const s1, const void *const s2)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
+{
+ const int v1 = ((fuzmatch_str_T *)s1)->score;
+ const int v2 = ((fuzmatch_str_T *)s2)->score;
+ const int idx1 = ((fuzmatch_str_T *)s1)->idx;
+ const int idx2 = ((fuzmatch_str_T *)s2)->idx;
+ const char *const str1 = ((fuzmatch_str_T *)s1)->str;
+ const char *const str2 = ((fuzmatch_str_T *)s2)->str;
+
+ if (*str1 != '<' && *str2 == '<') {
+ return -1;
+ }
+ if (*str1 == '<' && *str2 != '<') {
+ return 1;
+ }
+ return v1 == v2 ? (idx1 - idx2) : v1 > v2 ? -1 : 1;
+}
+
+/// Sort fuzzy matches of function names by score.
+/// <SNR> functions should be sorted to the end.
+static void fuzzy_match_func_sort(fuzmatch_str_T *const fm, const int sz)
+ FUNC_ATTR_NONNULL_ALL
+{
+ // Sort the list by the descending order of the match score
+ qsort(fm, (size_t)sz, sizeof(fuzmatch_str_T), fuzzy_match_func_compare);
+}
+
+/// Fuzzy match "pat" in "str".
+/// @returns 0 if there is no match. Otherwise, returns the match score.
+int fuzzy_match_str(char *const str, const char *const pat)
+ FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ if (str == NULL || pat == NULL) {
+ return 0;
+ }
+
+ int score = 0;
+ uint32_t matchpos[MAX_FUZZY_MATCHES];
+ fuzzy_match(str, pat, true, &score, matchpos, sizeof(matchpos) / sizeof(matchpos[0]));
+
+ return score;
+}
+
+/// Copy a list of fuzzy matches into a string list after sorting the matches by
+/// the fuzzy score. Frees the memory allocated for "fuzmatch".
+void fuzzymatches_to_strmatches(fuzmatch_str_T *const fuzmatch, char ***const matches,
+ const int count, const bool funcsort)
+ FUNC_ATTR_NONNULL_ARG(2)
+{
+ if (count <= 0) {
+ return;
+ }
+
+ *matches = xmalloc((size_t)count * sizeof(char *));
+
+ // Sort the list by the descending order of the match score
+ if (funcsort) {
+ fuzzy_match_func_sort(fuzmatch, count);
+ } else {
+ fuzzy_match_str_sort(fuzmatch, count);
+ }
+
+ for (int i = 0; i < count; i++) {
+ (*matches)[i] = fuzmatch[i].str;
+ }
+ xfree(fuzmatch);
+}
+
+/// Free a list of fuzzy string matches.
+void fuzmatch_str_free(fuzmatch_str_T *const fuzmatch, int count)
+{
+ if (count <= 0 || fuzmatch == NULL) {
+ return;
+ }
+ while (count--) {
+ xfree(fuzmatch[count].str);
+ }
+ xfree(fuzmatch);
+}
+
/// Get line "lnum" and copy it into "buf[LSIZE]".
/// The copy is made because the regexp may make the line invalid when using a
/// mark.
@@ -3534,9 +3658,9 @@ void find_pattern_in_path(char *ptr, Direction dir, size_t len, bool whole, bool
1L, p_fname);
} else {
// Use text after match with 'include'.
- new_fname = (char *)file_name_in_line((char_u *)incl_regmatch.endp[0], 0,
- FNAME_EXP|FNAME_INCL|FNAME_REL, 1L, (char_u *)p_fname,
- NULL);
+ new_fname = file_name_in_line(incl_regmatch.endp[0], 0,
+ FNAME_EXP|FNAME_INCL|FNAME_REL, 1L, p_fname,
+ NULL);
}
already_searched = false;
if (new_fname != NULL) {
diff --git a/src/nvim/search.h b/src/nvim/search.h
index 092098d5fd..2f140ba840 100644
--- a/src/nvim/search.h
+++ b/src/nvim/search.h
@@ -99,6 +99,14 @@ typedef struct searchstat {
int last_maxcount; // the max count of the last search
} searchstat_T;
+/// Fuzzy matched string list item. Used for fuzzy match completion. Items are
+/// usually sorted by "score". The "idx" member is used for stable-sort.
+typedef struct {
+ int idx;
+ char *str;
+ int score;
+} fuzmatch_str_T;
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "search.h.generated.h"
#endif
diff --git a/src/nvim/sha256.c b/src/nvim/sha256.c
index 72ef74b46c..db647f3ecb 100644
--- a/src/nvim/sha256.c
+++ b/src/nvim/sha256.c
@@ -32,10 +32,10 @@
}
#define PUT_UINT32(n, b, i) { \
- (b)[(i)] = (char_u)((n) >> 24); \
- (b)[(i) + 1] = (char_u)((n) >> 16); \
- (b)[(i) + 2] = (char_u)((n) >> 8); \
- (b)[(i) + 3] = (char_u)((n)); \
+ (b)[(i)] = (uint8_t)((n) >> 24); \
+ (b)[(i) + 1] = (uint8_t)((n) >> 16); \
+ (b)[(i) + 2] = (uint8_t)((n) >> 8); \
+ (b)[(i) + 3] = (uint8_t)((n)); \
}
void sha256_start(context_sha256_T *ctx)
@@ -53,7 +53,7 @@ void sha256_start(context_sha256_T *ctx)
ctx->state[7] = 0x5BE0CD19;
}
-static void sha256_process(context_sha256_T *ctx, const char_u data[SHA256_BUFFER_SIZE])
+static void sha256_process(context_sha256_T *ctx, const uint8_t data[SHA256_BUFFER_SIZE])
{
uint32_t temp1, temp2, W[SHA256_BUFFER_SIZE];
uint32_t A, B, C, D, E, F, G, H;
@@ -180,7 +180,7 @@ static void sha256_process(context_sha256_T *ctx, const char_u data[SHA256_BUFFE
ctx->state[7] += H;
}
-void sha256_update(context_sha256_T *ctx, const char_u *input, size_t length)
+void sha256_update(context_sha256_T *ctx, const uint8_t *input, size_t length)
{
if (length == 0) {
return;
@@ -198,7 +198,7 @@ void sha256_update(context_sha256_T *ctx, const char_u *input, size_t length)
size_t fill = SHA256_BUFFER_SIZE - left;
if (left && (length >= fill)) {
- memcpy((void *)(ctx->buffer + left), (void *)input, fill);
+ memcpy(ctx->buffer + left, input, fill);
sha256_process(ctx, ctx->buffer);
length -= fill;
input += fill;
@@ -212,22 +212,22 @@ void sha256_update(context_sha256_T *ctx, const char_u *input, size_t length)
}
if (length) {
- memcpy((void *)(ctx->buffer + left), (void *)input, length);
+ memcpy(ctx->buffer + left, input, length);
}
}
-static char_u sha256_padding[SHA256_BUFFER_SIZE] = {
+static uint8_t sha256_padding[SHA256_BUFFER_SIZE] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
-void sha256_finish(context_sha256_T *ctx, char_u digest[SHA256_SUM_SIZE])
+void sha256_finish(context_sha256_T *ctx, uint8_t digest[SHA256_SUM_SIZE])
{
uint32_t last, padn;
uint32_t high, low;
- char_u msglen[8];
+ uint8_t msglen[8];
high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
low = (ctx->total[0] << 3);
@@ -265,7 +265,7 @@ void sha256_finish(context_sha256_T *ctx, char_u digest[SHA256_SUM_SIZE])
const char *sha256_bytes(const uint8_t *restrict buf, size_t buf_len, const uint8_t *restrict salt,
size_t salt_len)
{
- char_u sha256sum[SHA256_SUM_SIZE];
+ uint8_t sha256sum[SHA256_SUM_SIZE];
static char hexit[SHA256_BUFFER_SIZE + 1]; // buf size + NULL
context_sha256_T ctx;
@@ -309,8 +309,8 @@ bool sha256_self_test(void)
{
char output[SHA256_BUFFER_SIZE + 1]; // buf size + NULL
context_sha256_T ctx;
- char_u buf[1000];
- char_u sha256sum[SHA256_SUM_SIZE];
+ uint8_t buf[1000];
+ uint8_t sha256sum[SHA256_SUM_SIZE];
const char *hexit;
static bool sha256_self_tested = false;
diff --git a/src/nvim/sha256.h b/src/nvim/sha256.h
index a1d8f670d5..eeb4031509 100644
--- a/src/nvim/sha256.h
+++ b/src/nvim/sha256.h
@@ -12,7 +12,7 @@
typedef struct {
uint32_t total[2];
uint32_t state[8];
- char_u buffer[SHA256_BUFFER_SIZE];
+ uint8_t buffer[SHA256_BUFFER_SIZE];
} context_sha256_T;
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index 754139a147..90a01aaf97 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -53,7 +53,6 @@
#include "nvim/search.h"
#include "nvim/shada.h"
#include "nvim/strings.h"
-#include "nvim/types.h"
#include "nvim/version.h"
#include "nvim/vim.h"
@@ -1483,7 +1482,7 @@ static char *shada_filename(const char *file)
if (p_shadafile != NULL && *p_shadafile != NUL) {
file = p_shadafile;
} else {
- if ((file = (char *)find_shada_parameter('n')) == NULL || *file == NUL) {
+ if ((file = find_shada_parameter('n')) == NULL || *file == NUL) {
file = shada_get_default_file();
}
// XXX It used to be one level lower, so that whatever is in
@@ -2668,8 +2667,6 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef
}
// Initialize jump list
- setpcmark();
- cleanup_jumplist(curwin, false);
wms->jumps_size = shada_init_jumps(wms->jumps, &removable_bufs);
const bool search_highlighted = !(no_hlsearch
@@ -4039,13 +4036,11 @@ static bool shada_removable(const char *name)
static inline size_t shada_init_jumps(PossiblyFreedShadaEntry *jumps,
khash_t(bufset) *const removable_bufs)
{
- if (!curwin->w_jumplistlen) {
- return 0;
- }
-
+ // Initialize jump list
size_t jumps_size = 0;
const void *jump_iter = NULL;
-
+ setpcmark();
+ cleanup_jumplist(curwin, false);
do {
xfmark_T fm;
jump_iter = mark_jumplist_iter(jump_iter, curwin, &fm);
@@ -4118,7 +4113,6 @@ void shada_encode_jumps(msgpack_sbuffer *const sbuf)
khash_t(bufset) removable_bufs = KHASH_EMPTY_TABLE(bufset);
find_removable_bufs(&removable_bufs);
PossiblyFreedShadaEntry jumps[JUMPLISTSIZE];
- cleanup_jumplist(curwin, true);
size_t jumps_size = shada_init_jumps(jumps, &removable_bufs);
msgpack_packer packer;
msgpack_packer_init(&packer, sbuf, msgpack_sbuffer_write);
diff --git a/src/nvim/sign.c b/src/nvim/sign.c
index e211b0069e..00e282b76e 100644
--- a/src/nvim/sign.c
+++ b/src/nvim/sign.c
@@ -99,16 +99,16 @@ static signgroup_T *sign_group_ref(const char *groupname)
hashitem_T *hi;
signgroup_T *group;
- hash = hash_hash((char_u *)groupname);
+ hash = hash_hash(groupname);
hi = hash_lookup(&sg_table, (char *)groupname, strlen(groupname), hash);
if (HASHITEM_EMPTY(hi)) {
// new group
- group = xmalloc(sizeof(signgroup_T) + strlen(groupname));
+ group = xmalloc(offsetof(signgroup_T, sg_name) + strlen(groupname) + 1);
STRCPY(group->sg_name, groupname);
group->sg_refcount = 1;
group->sg_next_sign_id = 1;
- hash_add_item(&sg_table, hi, (char_u *)group->sg_name, hash);
+ hash_add_item(&sg_table, hi, group->sg_name, hash);
} else {
// existing group
group = HI2SG(hi);
@@ -122,17 +122,17 @@ static signgroup_T *sign_group_ref(const char *groupname)
/// removed, then remove the group.
static void sign_group_unref(char *groupname)
{
- signgroup_T *group;
-
hashitem_T *hi = hash_find(&sg_table, groupname);
- if (!HASHITEM_EMPTY(hi)) {
- group = HI2SG(hi);
- group->sg_refcount--;
- if (group->sg_refcount == 0) {
- // All the signs in this group are removed
- hash_remove(&sg_table, hi);
- xfree(group);
- }
+ if (HASHITEM_EMPTY(hi)) {
+ return;
+ }
+
+ signgroup_T *group = HI2SG(hi);
+ group->sg_refcount--;
+ if (group->sg_refcount == 0) {
+ // All the signs in this group are removed
+ hash_remove(&sg_table, hi);
+ xfree(group);
}
}
diff --git a/src/nvim/sign_defs.h b/src/nvim/sign_defs.h
index 16e783aab7..7aa06ce48a 100644
--- a/src/nvim/sign_defs.h
+++ b/src/nvim/sign_defs.h
@@ -10,9 +10,9 @@
// Sign group
typedef struct signgroup_S {
- uint16_t sg_refcount; // number of signs in this group
- int sg_next_sign_id; // next sign id for this group
- char sg_name[1]; // sign group name
+ int sg_next_sign_id; ///< next sign id for this group
+ uint16_t sg_refcount; ///< number of signs in this group
+ char sg_name[1]; ///< sign group name, actually longer
} signgroup_T;
// Macros to get the sign group structure from the group name
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 48aed9c6de..2204cda169 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -123,7 +123,7 @@ enum {
slang_T *first_lang = NULL;
// file used for "zG" and "zW"
-char_u *int_wordlist = NULL;
+char *int_wordlist = NULL;
// Structure to store info for word matching.
typedef struct matchinf_S {
@@ -131,9 +131,9 @@ typedef struct matchinf_S {
// pointers to original text to be checked
char *mi_word; // start of word being checked
- char_u *mi_end; // end of matching word so far
- char_u *mi_fend; // next char to be added to mi_fword
- char_u *mi_cend; // char after what was used for
+ char *mi_end; // end of matching word so far
+ char *mi_fend; // next char to be added to mi_fword
+ char *mi_cend; // char after what was used for
// mi_capflags
// case-folded text
@@ -161,12 +161,12 @@ typedef struct matchinf_S {
// for NOBREAK
int mi_result2; // "mi_result" without following word
- char_u *mi_end2; // "mi_end" without following word
+ char *mi_end2; // "mi_end" without following word
} matchinf_T;
// Structure used for the cookie argument of do_in_runtimepath().
typedef struct spelload_S {
- char_u sl_lang[MAXWLEN + 1]; // language name
+ char sl_lang[MAXWLEN + 1]; // language name
slang_T *sl_slang; // resulting slang_T struct
int sl_nobreak; // NOBREAK language found
} spelload_T;
@@ -214,7 +214,7 @@ char *repl_to = NULL;
///
/// @return the length of the word in bytes, also when it's OK, so that the
/// caller can skip over the word.
-size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docount)
+size_t spell_check(win_T *wp, char *ptr, hlf_T *attrp, int *capcol, bool docount)
{
matchinf_T mi; // Most things are put in "mi" so that it can
// be passed to functions quickly.
@@ -226,7 +226,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
// A word never starts at a space or a control character. Return quickly
// then, skipping over the character.
- if (*ptr <= ' ') {
+ if ((uint8_t)(*ptr) <= ' ') {
return 1;
}
@@ -242,23 +242,23 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
// julifeest".
if (*ptr >= '0' && *ptr <= '9') {
if (*ptr == '0' && (ptr[1] == 'b' || ptr[1] == 'B')) {
- mi.mi_end = (char_u *)skipbin((char *)ptr + 2);
+ mi.mi_end = (char *)skipbin(ptr + 2);
} else if (*ptr == '0' && (ptr[1] == 'x' || ptr[1] == 'X')) {
- mi.mi_end = (char_u *)skiphex((char *)ptr + 2);
+ mi.mi_end = skiphex(ptr + 2);
} else {
- mi.mi_end = (char_u *)skipdigits((char *)ptr);
+ mi.mi_end = skipdigits(ptr);
}
nrlen = (size_t)(mi.mi_end - ptr);
}
// Find the normal end of the word (until the next non-word character).
- mi.mi_word = (char *)ptr;
+ mi.mi_word = ptr;
mi.mi_fend = ptr;
if (spell_iswordp(mi.mi_fend, wp)) {
bool this_upper = false; // init for gcc
if (use_camel_case) {
- int c = utf_ptr2char((char *)mi.mi_fend);
+ int c = utf_ptr2char(mi.mi_fend);
this_upper = SPELL_ISUPPER(c);
}
@@ -266,7 +266,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
MB_PTR_ADV(mi.mi_fend);
if (use_camel_case) {
const bool prev_upper = this_upper;
- int c = utf_ptr2char((char *)mi.mi_fend);
+ int c = utf_ptr2char(mi.mi_fend);
this_upper = SPELL_ISUPPER(c);
camel_case = !prev_upper && this_upper;
}
@@ -275,7 +275,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
if (capcol != NULL && *capcol == 0 && wp->w_s->b_cap_prog != NULL) {
// Check word starting with capital letter.
- int c = utf_ptr2char((char *)ptr);
+ int c = utf_ptr2char(ptr);
if (!SPELL_ISUPPER(c)) {
wrongcaplen = (size_t)(mi.mi_fend - ptr);
}
@@ -300,7 +300,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
MB_PTR_ADV(mi.mi_fend);
}
- (void)spell_casefold(wp, ptr, (int)(mi.mi_fend - ptr), (char_u *)mi.mi_fword,
+ (void)spell_casefold(wp, ptr, (int)(mi.mi_fend - ptr), mi.mi_fword,
MAXWLEN + 1);
mi.mi_fwordlen = (int)strlen(mi.mi_fword);
@@ -344,7 +344,7 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
// Count the word in the first language where it's found to be OK.
if (count_word && mi.mi_result == SP_OK) {
- count_common_word(mi.mi_lp->lp_slang, (char *)ptr,
+ count_common_word(mi.mi_lp->lp_slang, ptr,
(int)(mi.mi_end - ptr), 1);
count_word = false;
}
@@ -366,36 +366,36 @@ size_t spell_check(win_T *wp, char_u *ptr, hlf_T *attrp, int *capcol, bool docou
// Check for end of sentence.
regmatch.regprog = wp->w_s->b_cap_prog;
regmatch.rm_ic = false;
- int r = vim_regexec(&regmatch, (char *)ptr, 0);
+ int r = vim_regexec(&regmatch, ptr, 0);
wp->w_s->b_cap_prog = regmatch.regprog;
if (r) {
- *capcol = (int)(regmatch.endp[0] - (char *)ptr);
+ *capcol = (int)(regmatch.endp[0] - ptr);
}
}
- return (size_t)(utfc_ptr2len((char *)ptr));
+ return (size_t)(utfc_ptr2len(ptr));
} else if (mi.mi_end == ptr) {
// Always include at least one character. Required for when there
// is a mixup in "midword".
MB_PTR_ADV(mi.mi_end);
} else if (mi.mi_result == SP_BAD
&& LANGP_ENTRY(wp->w_s->b_langp, 0)->lp_slang->sl_nobreak) {
- char_u *p, *fp;
+ char *p, *fp;
int save_result = mi.mi_result;
// First language in 'spelllang' is NOBREAK. Find first position
// at which any word would be valid.
mi.mi_lp = LANGP_ENTRY(wp->w_s->b_langp, 0);
if (mi.mi_lp->lp_slang->sl_fidxs != NULL) {
- p = (char_u *)mi.mi_word;
- fp = (char_u *)mi.mi_fword;
+ p = mi.mi_word;
+ fp = mi.mi_fword;
for (;;) {
MB_PTR_ADV(p);
MB_PTR_ADV(fp);
if (p >= mi.mi_end) {
break;
}
- mi.mi_compoff = (int)(fp - (char_u *)mi.mi_fword);
+ mi.mi_compoff = (int)(fp - mi.mi_fword);
find_word(&mi, FIND_COMPOUND);
if (mi.mi_result != SP_BAD) {
mi.mi_end = p;
@@ -444,7 +444,7 @@ static void find_word(matchinf_T *mip, int mode)
// Check for word with matching case in keep-case tree.
ptr = mip->mi_word;
flen = 9999; // no case folding, always enough bytes
- byts = slang->sl_kbyts;
+ byts = (char_u *)slang->sl_kbyts;
idxs = slang->sl_kidxs;
if (mode == FIND_KEEPCOMPOUND) {
@@ -455,7 +455,7 @@ static void find_word(matchinf_T *mip, int mode)
// Check for case-folded in case-folded tree.
ptr = mip->mi_fword;
flen = mip->mi_fwordlen; // available case-folded bytes
- byts = slang->sl_fbyts;
+ byts = (char_u *)slang->sl_fbyts;
idxs = slang->sl_fidxs;
if (mode == FIND_PREFIX) {
@@ -575,7 +575,7 @@ static void find_word(matchinf_T *mip, int mode)
if (utf_head_off(ptr, ptr + wlen) > 0) {
continue; // not at first byte of character
}
- if (spell_iswordp((char_u *)ptr + wlen, mip->mi_win)) {
+ if (spell_iswordp(ptr + wlen, mip->mi_win)) {
if (slang->sl_compprog == NULL && !slang->sl_nobreak) {
continue; // next char is a word character
}
@@ -612,11 +612,11 @@ static void find_word(matchinf_T *mip, int mode)
// For keep-case tree the case is always right. For prefixes we
// don't bother to check.
if (mode == FIND_FOLDWORD) {
- if (mip->mi_cend != (char_u *)mip->mi_word + wlen) {
+ if (mip->mi_cend != mip->mi_word + wlen) {
// mi_capflags was set for a different word length, need
// to do it again.
- mip->mi_cend = (char_u *)mip->mi_word + wlen;
- mip->mi_capflags = captype((char_u *)mip->mi_word, mip->mi_cend);
+ mip->mi_cend = mip->mi_word + wlen;
+ mip->mi_capflags = captype(mip->mi_word, mip->mi_cend);
}
if (mip->mi_capflags == WF_KEEPCAP
@@ -629,7 +629,7 @@ static void find_word(matchinf_T *mip, int mode)
// mip->mi_prefarridx that find_prefix() filled.
c = valid_word_prefix(mip->mi_prefcnt, mip->mi_prefarridx,
(int)flags,
- (char_u *)mip->mi_word + mip->mi_cprefixlen, slang,
+ mip->mi_word + mip->mi_cprefixlen, slang,
false);
if (c == 0) {
continue;
@@ -664,7 +664,7 @@ static void find_word(matchinf_T *mip, int mode)
// For multi-byte chars check character length against
// COMPOUNDMIN.
if (slang->sl_compminlen > 0
- && mb_charlen_len((char_u *)mip->mi_word + mip->mi_compoff,
+ && mb_charlen_len(mip->mi_word + mip->mi_compoff,
wlen - mip->mi_compoff) < slang->sl_compminlen) {
continue;
}
@@ -687,7 +687,8 @@ static void find_word(matchinf_T *mip, int mode)
}
// Quickly check if compounding is possible with this flag.
- if (!byte_in_str(mip->mi_complen == 0 ? slang->sl_compstartflags : slang->sl_compallflags,
+ if (!byte_in_str(mip->mi_complen ==
+ 0 ? slang->sl_compstartflags : slang->sl_compallflags,
(int)((unsigned)flags >> 24))) {
continue;
}
@@ -712,7 +713,7 @@ static void find_word(matchinf_T *mip, int mode)
} else {
p = mip->mi_word + mip->mi_compoff;
}
- capflags = captype((char_u *)p, (char_u *)mip->mi_word + wlen);
+ capflags = captype(p, mip->mi_word + wlen);
if (capflags == WF_KEEPCAP || (capflags == WF_ALLCAP
&& (flags & WF_FIXCAP) != 0)) {
continue;
@@ -724,7 +725,7 @@ static void find_word(matchinf_T *mip, int mode)
// accept a no-caps word, even when the dictionary
// word specifies ONECAP.
MB_PTR_BACK(mip->mi_word, p);
- if (spell_iswordp_nmw((char_u *)p, mip->mi_win)
+ if (spell_iswordp_nmw(p, mip->mi_win)
? capflags == WF_ONECAP
: (flags & WF_ONECAP) != 0
&& capflags != WF_ONECAP) {
@@ -744,12 +745,12 @@ static void find_word(matchinf_T *mip, int mode)
if (slang->sl_compsylmax < MAXWLEN) {
// "fword" is only needed for checking syllables.
if (ptr == mip->mi_word) {
- (void)spell_casefold(mip->mi_win, (char_u *)ptr, wlen, (char_u *)fword, MAXWLEN);
+ (void)spell_casefold(mip->mi_win, ptr, wlen, fword, MAXWLEN);
} else {
xstrlcpy(fword, ptr, (size_t)endlen[endidxcnt] + 1);
}
}
- if (!can_compound(slang, (char *)fword, mip->mi_compflags)) {
+ if (!can_compound(slang, fword, mip->mi_compflags)) {
continue;
}
} else if (slang->sl_comprules != NULL
@@ -767,7 +768,7 @@ static void find_word(matchinf_T *mip, int mode)
if (!word_ends) {
int save_result = mip->mi_result;
- char_u *save_end = mip->mi_end;
+ char *save_end = mip->mi_end;
langp_T *save_lp = mip->mi_lp;
// Check that a valid word follows. If there is one and we
@@ -878,16 +879,16 @@ static void find_word(matchinf_T *mip, int mode)
if (nobreak_result == SP_BAD) {
if (mip->mi_result2 > res) {
mip->mi_result2 = res;
- mip->mi_end2 = (char_u *)mip->mi_word + wlen;
+ mip->mi_end2 = mip->mi_word + wlen;
} else if (mip->mi_result2 == res
- && mip->mi_end2 < (char_u *)mip->mi_word + wlen) {
- mip->mi_end2 = (char_u *)mip->mi_word + wlen;
+ && mip->mi_end2 < mip->mi_word + wlen) {
+ mip->mi_end2 = mip->mi_word + wlen;
}
} else if (mip->mi_result > res) {
mip->mi_result = res;
- mip->mi_end = (char_u *)mip->mi_word + wlen;
- } else if (mip->mi_result == res && mip->mi_end < (char_u *)mip->mi_word + wlen) {
- mip->mi_end = (char_u *)mip->mi_word + wlen;
+ mip->mi_end = mip->mi_word + wlen;
+ } else if (mip->mi_result == res && mip->mi_end < mip->mi_word + wlen) {
+ mip->mi_end = mip->mi_word + wlen;
}
if (mip->mi_result == SP_OK) {
@@ -930,15 +931,15 @@ bool match_checkcompoundpattern(char *ptr, int wlen, garray_T *gap)
bool can_compound(slang_T *slang, const char *word, const uint8_t *flags)
FUNC_ATTR_NONNULL_ALL
{
- char_u uflags[MAXWLEN * 2] = { 0 };
+ char uflags[MAXWLEN * 2] = { 0 };
if (slang->sl_compprog == NULL) {
return false;
}
// Need to convert the single byte flags to utf8 characters.
- char_u *p = uflags;
+ char *p = uflags;
for (int i = 0; flags[i] != NUL; i++) {
- p += utf_char2bytes(flags[i], (char *)p);
+ p += utf_char2bytes(flags[i], p);
}
*p = NUL;
p = uflags;
@@ -950,7 +951,7 @@ bool can_compound(slang_T *slang, const char *word, const uint8_t *flags)
// are too many syllables AND the number of compound words is above
// COMPOUNDWORDMAX then compounding is not allowed.
if (slang->sl_compsylmax < MAXWLEN
- && count_syllables(slang, (char_u *)word) > slang->sl_compsylmax) {
+ && count_syllables(slang, word) > slang->sl_compsylmax) {
return (int)strlen((char *)flags) < slang->sl_compmax;
}
return true;
@@ -963,7 +964,7 @@ bool can_compound(slang_T *slang, const char *word, const uint8_t *flags)
bool match_compoundrule(slang_T *slang, const char_u *compflags)
{
// loop over all the COMPOUNDRULE entries
- for (char_u *p = slang->sl_comprules; *p != NUL; p++) {
+ for (char_u *p = (char_u *)slang->sl_comprules; *p != NUL; p++) {
// loop over the flags in the compound word we have made, match
// them against the current rule entry
for (int i = 0;; i++) {
@@ -1013,7 +1014,7 @@ bool match_compoundrule(slang_T *slang, const char_u *compflags)
/// @param totprefcnt nr of prefix IDs
/// @param arridx idx in sl_pidxs[]
/// @param cond_req only use prefixes with a condition
-int valid_word_prefix(int totprefcnt, int arridx, int flags, char_u *word, slang_T *slang,
+int valid_word_prefix(int totprefcnt, int arridx, int flags, char *word, slang_T *slang,
bool cond_req)
{
int prefid = (int)((unsigned)flags >> 24);
@@ -1061,7 +1062,7 @@ static void find_prefix(matchinf_T *mip, int mode)
int wlen = 0;
slang_T *slang = mip->mi_lp->lp_slang;
- char_u *byts = slang->sl_pbyts;
+ char_u *byts = (char_u *)slang->sl_pbyts;
if (byts == NULL) {
return; // array is empty
}
@@ -1110,8 +1111,8 @@ static void find_prefix(matchinf_T *mip, int mode)
}
// Case-folded length may differ from original length.
- mip->mi_cprefixlen = nofold_len((char_u *)mip->mi_fword, mip->mi_prefixlen,
- (char_u *)mip->mi_word);
+ mip->mi_cprefixlen = nofold_len(mip->mi_fword, mip->mi_prefixlen,
+ mip->mi_word);
find_word(mip, FIND_PREFIX);
if (len == 0) {
@@ -1157,7 +1158,7 @@ static void find_prefix(matchinf_T *mip, int mode)
// Return the length of the folded chars in bytes.
static int fold_more(matchinf_T *mip)
{
- char_u *p = mip->mi_fend;
+ char *p = mip->mi_fend;
do {
MB_PTR_ADV(mip->mi_fend);
} while (*mip->mi_fend != NUL && spell_iswordp(mip->mi_fend, mip->mi_win));
@@ -1168,7 +1169,7 @@ static int fold_more(matchinf_T *mip)
}
(void)spell_casefold(mip->mi_win, p, (int)(mip->mi_fend - p),
- (char_u *)mip->mi_fword + mip->mi_fwordlen,
+ mip->mi_fword + mip->mi_fwordlen,
MAXWLEN - mip->mi_fwordlen);
int flen = (int)strlen(mip->mi_fword + mip->mi_fwordlen);
mip->mi_fwordlen += flen;
@@ -1319,7 +1320,7 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att
STRCPY(buf, line);
if (lnum < wp->w_buffer->b_ml.ml_line_count) {
spell_cat_line(buf + strlen(buf),
- (char_u *)ml_get_buf(wp->w_buffer, lnum + 1, false),
+ ml_get_buf(wp->w_buffer, lnum + 1, false),
MAXWLEN);
}
char *p = buf + skip;
@@ -1336,7 +1337,7 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att
// start of word
attr = HLF_COUNT;
- len = spell_check(wp, (char_u *)p, &attr, &capcol, false);
+ len = spell_check(wp, p, &attr, &capcol, false);
if (attr != HLF_COUNT) {
// We found a bad word. Check the attribute.
@@ -1480,27 +1481,29 @@ theend:
// "buf", blanking-out special characters. Copy less than "maxlen" bytes.
// Keep the blanks at the start of the next line, this is used in win_line()
// to skip those bytes if the word was OK.
-void spell_cat_line(char *buf, char_u *line, int maxlen)
+void spell_cat_line(char *buf, char *line, int maxlen)
{
- char_u *p = (char_u *)skipwhite((char *)line);
- while (vim_strchr("*#/\"\t", *p) != NULL) {
+ char_u *p = (char_u *)skipwhite(line);
+ while (vim_strchr("*#/\"\t", (uint8_t)(*p)) != NULL) {
p = (char_u *)skipwhite((char *)p + 1);
}
- if (*p != NUL) {
- // Only worth concatenating if there is something else than spaces to
- // concatenate.
- int n = (int)(p - line) + 1;
- if (n < maxlen - 1) {
- memset(buf, ' ', (size_t)n);
- xstrlcpy(buf + n, (char *)p, (size_t)(maxlen - n));
- }
+ if (*p == NUL) {
+ return;
+ }
+
+ // Only worth concatenating if there is something else than spaces to
+ // concatenate.
+ int n = (int)(p - (char_u *)line) + 1;
+ if (n < maxlen - 1) {
+ memset(buf, ' ', (size_t)n);
+ xstrlcpy(buf + n, (char *)p, (size_t)(maxlen - n));
}
}
// Load word list(s) for "lang" from Vim spell file(s).
// "lang" must be the language without the region: e.g., "en".
-static void spell_load_lang(char_u *lang)
+static void spell_load_lang(char *lang)
{
char fname_enc[85];
int r;
@@ -1520,18 +1523,18 @@ static void spell_load_lang(char_u *lang)
// autocommand may load it then.
for (int round = 1; round <= 2; round++) {
// Find the first spell file for "lang" in 'runtimepath' and load it.
- vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5,
+ vim_snprintf(fname_enc, sizeof(fname_enc) - 5,
"spell/%s.%s.spl", lang, spell_enc());
- r = do_in_runtimepath((char *)fname_enc, 0, spell_load_cb, &sl);
+ r = do_in_runtimepath(fname_enc, 0, spell_load_cb, &sl);
if (r == FAIL && *sl.sl_lang != NUL) {
// Try loading the ASCII version.
- vim_snprintf((char *)fname_enc, sizeof(fname_enc) - 5,
+ vim_snprintf(fname_enc, sizeof(fname_enc) - 5,
"spell/%s.ascii.spl", lang);
- r = do_in_runtimepath((char *)fname_enc, 0, spell_load_cb, &sl);
+ r = do_in_runtimepath(fname_enc, 0, spell_load_cb, &sl);
if (r == FAIL && *sl.sl_lang != NUL && round == 1
- && apply_autocmds(EVENT_SPELLFILEMISSING, (char *)lang,
+ && apply_autocmds(EVENT_SPELLFILEMISSING, lang,
curbuf->b_fname, false, curbuf)) {
continue;
}
@@ -1556,7 +1559,7 @@ static void spell_load_lang(char_u *lang)
} else if (sl.sl_slang != NULL) {
// At least one file was loaded, now load ALL the additions.
STRCPY(fname_enc + strlen(fname_enc) - 3, "add.spl");
- do_in_runtimepath((char *)fname_enc, DIP_ALL, spell_load_cb, &sl);
+ do_in_runtimepath(fname_enc, DIP_ALL, spell_load_cb, &sl);
}
curbuf->b_locked--;
@@ -1564,19 +1567,19 @@ static void spell_load_lang(char_u *lang)
// Return the encoding used for spell checking: Use 'encoding', except that we
// use "latin1" for "latin9". And limit to 60 characters (just in case).
-char_u *spell_enc(void)
+char *spell_enc(void)
{
if (strlen(p_enc) < 60 && strcmp(p_enc, "iso-8859-15") != 0) {
- return (char_u *)p_enc;
+ return p_enc;
}
- return (char_u *)"latin1";
+ return "latin1";
}
// Get the name of the .spl file for the internal wordlist into
// "fname[MAXPATHL]".
-static void int_wordlist_spl(char_u *fname)
+static void int_wordlist_spl(char *fname)
{
- vim_snprintf((char *)fname, MAXPATHL, SPL_FNAME_TMPL,
+ vim_snprintf(fname, MAXPATHL, SPL_FNAME_TMPL,
int_wordlist, spell_enc());
}
@@ -1700,18 +1703,20 @@ void slang_clear_sug(slang_T *lp)
static void spell_load_cb(char *fname, void *cookie)
{
spelload_T *slp = (spelload_T *)cookie;
- slang_T *slang = spell_load_file(fname, (char *)slp->sl_lang, NULL, false);
- if (slang != NULL) {
- // When a previously loaded file has NOBREAK also use it for the
- // ".add" files.
- if (slp->sl_nobreak && slang->sl_add) {
- slang->sl_nobreak = true;
- } else if (slang->sl_nobreak) {
- slp->sl_nobreak = true;
- }
+ slang_T *slang = spell_load_file(fname, slp->sl_lang, NULL, false);
+ if (slang == NULL) {
+ return;
+ }
- slp->sl_slang = slang;
+ // When a previously loaded file has NOBREAK also use it for the
+ // ".add" files.
+ if (slp->sl_nobreak && slang->sl_add) {
+ slang->sl_nobreak = true;
+ } else if (slang->sl_nobreak) {
+ slp->sl_nobreak = true;
}
+
+ slp->sl_slang = slang;
}
/// Add a word to the hashtable of common words.
@@ -1736,14 +1741,14 @@ void count_common_word(slang_T *lp, char *word, int len, uint8_t count)
}
wordcount_T *wc;
- hash_T hash = hash_hash((char_u *)p);
+ hash_T hash = hash_hash(p);
const size_t p_len = strlen(p);
hashitem_T *hi = hash_lookup(&lp->sl_wordcount, (const char *)p, p_len, hash);
if (HASHITEM_EMPTY(hi)) {
- wc = xmalloc(sizeof(wordcount_T) + p_len);
+ wc = xmalloc(offsetof(wordcount_T, wc_word) + p_len + 1);
memcpy(wc->wc_word, p, p_len + 1);
wc->wc_count = count;
- hash_add_item(&lp->sl_wordcount, hi, wc->wc_word, hash);
+ hash_add_item(&lp->sl_wordcount, hi, (char *)wc->wc_word, hash);
} else {
wc = HI2WC(hi);
wc->wc_count = (uint16_t)(wc->wc_count + count);
@@ -1755,9 +1760,9 @@ void count_common_word(slang_T *lp, char *word, int len, uint8_t count)
// Returns true if byte "n" appears in "str".
// Like strchr() but independent of locale.
-bool byte_in_str(char_u *str, int n)
+bool byte_in_str(uint8_t *str, int n)
{
- for (char_u *p = str; *p != NUL; p++) {
+ for (uint8_t *p = str; *p != NUL; p++) {
if (*p == n) {
return true;
}
@@ -1798,7 +1803,7 @@ int init_syl_tab(slang_T *slang)
// Count the number of syllables in "word".
// When "word" contains spaces the syllables after the last space are counted.
// Returns zero if syllables are not defines.
-static int count_syllables(slang_T *slang, const char_u *word)
+static int count_syllables(slang_T *slang, const char *word)
FUNC_ATTR_NONNULL_ALL
{
int cnt = 0;
@@ -1809,7 +1814,7 @@ static int count_syllables(slang_T *slang, const char_u *word)
return 0;
}
- for (const char *p = (char *)word; *p != NUL; p += len) {
+ for (const char *p = word; *p != NUL; p += len) {
// When running into a space reset counter.
if (*p == ' ') {
len = 1;
@@ -1893,11 +1898,11 @@ char *did_set_spelllang(win_T *wp)
// Loop over comma separated language names.
for (splp = spl_copy; *splp != NUL;) {
// Get one language name.
- copy_option_part(&splp, (char *)lang, MAXWLEN, ",");
+ copy_option_part(&splp, lang, MAXWLEN, ",");
region = NULL;
len = (int)strlen(lang);
- if (!valid_spelllang((char *)lang)) {
+ if (!valid_spelllang(lang)) {
continue;
}
@@ -1913,7 +1918,7 @@ char *did_set_spelllang(win_T *wp)
filename = true;
// Locate a region and remove it from the file name.
- p = vim_strchr(path_tail((char *)lang), '_');
+ p = vim_strchr(path_tail(lang), '_');
if (p != NULL && ASCII_ISALPHA(p[1]) && ASCII_ISALPHA(p[2])
&& !ASCII_ISALPHA(p[3])) {
xstrlcpy(region_cp, p + 1, 3);
@@ -1925,7 +1930,7 @@ char *did_set_spelllang(win_T *wp)
// Check if we loaded this language before.
for (slang = first_lang; slang != NULL; slang = slang->sl_next) {
- if (path_full_compare((char *)lang, slang->sl_fname, false, true)
+ if (path_full_compare(lang, slang->sl_fname, false, true)
== kEqualFiles) {
break;
}
@@ -1959,9 +1964,9 @@ char *did_set_spelllang(win_T *wp)
// If not found try loading the language now.
if (slang == NULL) {
if (filename) {
- (void)spell_load_file((char *)lang, (char *)lang, NULL, false);
+ (void)spell_load_file(lang, lang, NULL, false);
} else {
- spell_load_lang((char_u *)lang);
+ spell_load_lang(lang);
// SpellFileMissing autocommands may do anything, including
// destroying the buffer we are using or closing the window.
if (!bufref_valid(&bufref) || !win_valid_any_tab(wp)) {
@@ -1974,12 +1979,12 @@ char *did_set_spelllang(win_T *wp)
// Loop over the languages, there can be several files for "lang".
for (slang = first_lang; slang != NULL; slang = slang->sl_next) {
if (filename
- ? path_full_compare((char *)lang, slang->sl_fname, false, true) == kEqualFiles
+ ? path_full_compare(lang, slang->sl_fname, false, true) == kEqualFiles
: STRICMP(lang, slang->sl_name) == 0) {
region_mask = REGION_ALL;
if (!filename && region != NULL) {
// find region in sl_regions
- c = find_region(slang->sl_regions, (char_u *)region);
+ c = find_region(slang->sl_regions, region);
if (c == REGION_ALL) {
if (slang->sl_add) {
if (*slang->sl_regions != NUL) {
@@ -2022,17 +2027,17 @@ char *did_set_spelllang(win_T *wp)
if (int_wordlist == NULL) {
continue;
}
- int_wordlist_spl((char_u *)spf_name);
+ int_wordlist_spl(spf_name);
} else {
// One entry in 'spellfile'.
- copy_option_part(&spf, (char *)spf_name, MAXPATHL - 5, ",");
+ copy_option_part(&spf, spf_name, MAXPATHL - 5, ",");
STRCAT(spf_name, ".spl");
// If it was already found above then skip it.
for (c = 0; c < ga.ga_len; c++) {
p = LANGP_ENTRY(ga, c)->lp_slang->sl_fname;
if (p != NULL
- && path_full_compare((char *)spf_name, p, false, true) == kEqualFiles) {
+ && path_full_compare(spf_name, p, false, true) == kEqualFiles) {
break;
}
}
@@ -2043,7 +2048,7 @@ char *did_set_spelllang(win_T *wp)
// Check if it was loaded already.
for (slang = first_lang; slang != NULL; slang = slang->sl_next) {
- if (path_full_compare((char *)spf_name, slang->sl_fname, false, true)
+ if (path_full_compare(spf_name, slang->sl_fname, false, true)
== kEqualFiles) {
break;
}
@@ -2055,13 +2060,13 @@ char *did_set_spelllang(win_T *wp)
if (round == 0) {
STRCPY(lang, "internal wordlist");
} else {
- xstrlcpy(lang, path_tail((char *)spf_name), MAXWLEN + 1);
- p = vim_strchr((char *)lang, '.');
+ xstrlcpy(lang, path_tail(spf_name), MAXWLEN + 1);
+ p = vim_strchr(lang, '.');
if (p != NULL) {
*p = NUL; // truncate at ".encoding.add"
}
}
- slang = spell_load_file((char *)spf_name, (char *)lang, NULL, true);
+ slang = spell_load_file(spf_name, lang, NULL, true);
// If one of the languages has NOBREAK we assume the addition
// files also have this.
@@ -2073,7 +2078,7 @@ char *did_set_spelllang(win_T *wp)
region_mask = REGION_ALL;
if (use_region != NULL && !dont_use_region) {
// find region in sl_regions
- c = find_region(slang->sl_regions, (char_u *)use_region);
+ c = find_region(slang->sl_regions, use_region);
if (c != REGION_ALL) {
region_mask = 1 << c;
} else if (*slang->sl_regions != NUL) {
@@ -2185,7 +2190,7 @@ static void use_midword(slang_T *lp, win_T *wp)
// Find the region "region[2]" in "rp" (points to "sl_regions").
// Each region is simply stored as the two characters of its name.
// Returns the index if found (first is 0), REGION_ALL if not found.
-static int find_region(const char_u *rp, const char_u *region)
+static int find_region(const char *rp, const char *region)
{
int i;
@@ -2210,10 +2215,10 @@ static int find_region(const char_u *rp, const char_u *region)
/// @param[in] end End of word or NULL for NUL delimited string
///
/// @returns Case type of word
-int captype(char_u *word, const char_u *end)
+int captype(char *word, const char *end)
FUNC_ATTR_NONNULL_ARG(1)
{
- char_u *p;
+ char *p;
// find first letter
for (p = word; !spell_iswordp_nmw(p, curwin); MB_PTR_ADV(p)) {
@@ -2221,7 +2226,7 @@ int captype(char_u *word, const char_u *end)
return 0; // only non-word characters, illegal word
}
}
- int c = mb_ptr2char_adv((const char_u **)&p);
+ int c = mb_ptr2char_adv((const char **)&p);
bool allcap;
bool firstcap = allcap = SPELL_ISUPPER(c);
bool past_second = false; // past second word char
@@ -2230,7 +2235,7 @@ int captype(char_u *word, const char_u *end)
// But a word with an upper char only at start is a ONECAP.
for (; end == NULL ? *p != NUL : p < end; MB_PTR_ADV(p)) {
if (spell_iswordp_nmw(p, curwin)) {
- c = utf_ptr2char((char *)p);
+ c = utf_ptr2char(p);
if (!SPELL_ISUPPER(c)) {
// UUl -> KEEPCAP
if (past_second && allcap) {
@@ -2257,13 +2262,15 @@ int captype(char_u *word, const char_u *end)
// Delete the internal wordlist and its .spl file.
void spell_delete_wordlist(void)
{
- if (int_wordlist != NULL) {
- char_u fname[MAXPATHL] = { 0 };
- os_remove((char *)int_wordlist);
- int_wordlist_spl(fname);
- os_remove((char *)fname);
- XFREE_CLEAR(int_wordlist);
+ if (int_wordlist == NULL) {
+ return;
}
+
+ char fname[MAXPATHL] = { 0 };
+ os_remove(int_wordlist);
+ int_wordlist_spl(fname);
+ os_remove(fname);
+ XFREE_CLEAR(int_wordlist);
}
// Free all languages.
@@ -2331,10 +2338,12 @@ buf_T *open_spellbuf(void)
// Close the buffer used for spell info.
void close_spellbuf(buf_T *buf)
{
- if (buf != NULL) {
- ml_close(buf, true);
- xfree(buf);
+ if (buf == NULL) {
+ return;
}
+
+ ml_close(buf, true);
+ xfree(buf);
}
// Init the chartab used for spelling for ASCII.
@@ -2393,18 +2402,18 @@ void init_spell_chartab(void)
/// Thus this only works properly when past the first character of the word.
///
/// @param wp Buffer used.
-bool spell_iswordp(const char_u *p, const win_T *wp)
+bool spell_iswordp(const char *p, const win_T *wp)
FUNC_ATTR_NONNULL_ALL
{
- const int l = utfc_ptr2len((char *)p);
- const char_u *s = p;
+ const int l = utfc_ptr2len(p);
+ const char *s = p;
if (l == 1) {
// be quick for ASCII
- if (wp->w_s->b_spell_ismw[*p]) {
+ if (wp->w_s->b_spell_ismw[(uint8_t)(*p)]) {
s = p + 1; // skip a mid-word character
}
} else {
- int c = utf_ptr2char((char *)p);
+ int c = utf_ptr2char(p);
if (c < 256
? wp->w_s->b_spell_ismw[c]
: (wp->w_s->b_spell_ismw_mb != NULL
@@ -2413,20 +2422,20 @@ bool spell_iswordp(const char_u *p, const win_T *wp)
}
}
- int c = utf_ptr2char((char *)s);
+ int c = utf_ptr2char(s);
if (c > 255) {
- return spell_mb_isword_class(mb_get_class((char *)s), wp);
+ return spell_mb_isword_class(mb_get_class(s), wp);
}
return spelltab.st_isw[c];
}
// Returns true if "p" points to a word character.
// Unlike spell_iswordp() this doesn't check for "midword" characters.
-bool spell_iswordp_nmw(const char_u *p, win_T *wp)
+bool spell_iswordp_nmw(const char *p, win_T *wp)
{
- int c = utf_ptr2char((char *)p);
+ int c = utf_ptr2char(p);
if (c > 255) {
- return spell_mb_isword_class(mb_get_class((char *)p), wp);
+ return spell_mb_isword_class(mb_get_class(p), wp);
}
return spelltab.st_isw[c];
}
@@ -2471,7 +2480,7 @@ static bool spell_iswordp_w(const int *p, const win_T *wp)
// Uses the character definitions from the .spl file.
// When using a multi-byte 'encoding' the length may change!
// Returns FAIL when something wrong.
-int spell_casefold(const win_T *wp, char_u *str, int len, char_u *buf, int buflen)
+int spell_casefold(const win_T *wp, char *str, int len, char *buf, int buflen)
FUNC_ATTR_NONNULL_ALL
{
if (len >= buflen) {
@@ -2482,12 +2491,12 @@ int spell_casefold(const win_T *wp, char_u *str, int len, char_u *buf, int bufle
int outi = 0;
// Fold one character at a time.
- for (char_u *p = str; p < str + len;) {
+ for (char *p = str; p < str + len;) {
if (outi + MB_MAXBYTES > buflen) {
buf[outi] = NUL;
return FAIL;
}
- int c = mb_cptr2char_adv((const char_u **)&p);
+ int c = mb_cptr2char_adv((const char **)&p);
// Exception: greek capital sigma 0x03A3 folds to 0x03C3, except
// when it is the last character in a word, then it folds to
@@ -2502,7 +2511,7 @@ int spell_casefold(const win_T *wp, char_u *str, int len, char_u *buf, int bufle
c = SPELL_TOFOLD(c);
}
- outi += utf_char2bytes(c, (char *)buf + outi);
+ outi += utf_char2bytes(c, buf + outi);
}
buf[outi] = NUL;
@@ -2551,7 +2560,7 @@ bool check_need_cap(linenr_T lnum, colnr_T col)
char *p = line + endcol;
for (;;) {
MB_PTR_BACK(line, p);
- if (p == line || spell_iswordp_nmw((char_u *)p, curwin)) {
+ if (p == line || spell_iswordp_nmw(p, curwin)) {
break;
}
if (vim_regexec(&regmatch, p, 0)
@@ -2582,15 +2591,15 @@ void ex_spellrepall(exarg_T *eap)
int addlen = (int)(strlen(repl_to) - strlen(repl_from));
size_t frompatlen = strlen(repl_from) + 7;
- char_u *frompat = xmalloc(frompatlen);
- snprintf((char *)frompat, frompatlen, "\\V\\<%s\\>", repl_from);
+ char *frompat = xmalloc(frompatlen);
+ snprintf(frompat, frompatlen, "\\V\\<%s\\>", repl_from);
p_ws = false;
sub_nsubs = 0;
sub_nlines = 0;
curwin->w_cursor.lnum = 0;
while (!got_int) {
- if (do_search(NULL, '/', '/', (char *)frompat, 1L, SEARCH_KEEP, NULL) == 0
+ if (do_search(NULL, '/', '/', frompat, 1L, SEARCH_KEEP, NULL) == 0
|| u_save_cursor() == FAIL) {
break;
}
@@ -2600,11 +2609,11 @@ void ex_spellrepall(exarg_T *eap)
char *line = get_cursor_line_ptr();
if (addlen <= 0 || strncmp(line + curwin->w_cursor.col,
repl_to, strlen(repl_to)) != 0) {
- char_u *p = xmalloc(strlen(line) + (size_t)addlen + 1);
+ char *p = xmalloc(strlen(line) + (size_t)addlen + 1);
memmove(p, line, (size_t)curwin->w_cursor.col);
STRCPY(p + curwin->w_cursor.col, repl_to);
STRCAT(p, line + curwin->w_cursor.col + strlen(repl_from));
- ml_replace(curwin->w_cursor.lnum, (char *)p, false);
+ ml_replace(curwin->w_cursor.lnum, p, false);
changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
if (curwin->w_cursor.lnum != prev_lnum) {
@@ -2634,30 +2643,30 @@ void ex_spellrepall(exarg_T *eap)
/// @param[in] word source string to copy
/// @param[in,out] wcopy copied string, with case of first letter changed
/// @param[in] upper True to upper case, otherwise lower case
-void onecap_copy(char_u *word, char *wcopy, bool upper)
+void onecap_copy(char *word, char *wcopy, bool upper)
{
- char_u *p = word;
- int c = mb_cptr2char_adv((const char_u **)&p);
+ char *p = word;
+ int c = mb_cptr2char_adv((const char **)&p);
if (upper) {
c = SPELL_TOUPPER(c);
} else {
c = SPELL_TOFOLD(c);
}
int l = utf_char2bytes(c, wcopy);
- xstrlcpy(wcopy + l, (char *)p, (size_t)(MAXWLEN - l));
+ xstrlcpy(wcopy + l, p, (size_t)(MAXWLEN - l));
}
// Make a copy of "word" with all the letters upper cased into
// "wcopy[MAXWLEN]". The result is NUL terminated.
-void allcap_copy(char_u *word, char_u *wcopy)
+void allcap_copy(char *word, char *wcopy)
{
- char_u *d = wcopy;
- for (char_u *s = word; *s != NUL;) {
- int c = mb_cptr2char_adv((const char_u **)&s);
+ char_u *d = (char_u *)wcopy;
+ for (char *s = word; *s != NUL;) {
+ int c = mb_cptr2char_adv((const char **)&s);
if (c == 0xdf) {
c = 'S';
- if (d - wcopy >= MAXWLEN - 1) {
+ if (d - (char_u *)wcopy >= MAXWLEN - 1) {
break;
}
*d++ = (char_u)c;
@@ -2665,7 +2674,7 @@ void allcap_copy(char_u *word, char_u *wcopy)
c = SPELL_TOUPPER(c);
}
- if (d - wcopy >= MAXWLEN - MB_MAXBYTES) {
+ if (d - (char_u *)wcopy >= MAXWLEN - MB_MAXBYTES) {
break;
}
d += utf_char2bytes(c, (char *)d);
@@ -2675,9 +2684,9 @@ void allcap_copy(char_u *word, char_u *wcopy)
// Case-folding may change the number of bytes: Count nr of chars in
// fword[flen] and return the byte length of that many chars in "word".
-int nofold_len(char_u *fword, int flen, char_u *word)
+int nofold_len(char *fword, int flen, char *word)
{
- char_u *p;
+ char *p;
int i = 0;
for (p = fword; p < fword + flen; MB_PTR_ADV(p)) {
@@ -2690,14 +2699,14 @@ int nofold_len(char_u *fword, int flen, char_u *word)
}
// Copy "fword" to "cword", fixing case according to "flags".
-void make_case_word(char_u *fword, char_u *cword, int flags)
+void make_case_word(char *fword, char *cword, int flags)
{
if (flags & WF_ALLCAP) {
// Make it all upper-case
allcap_copy(fword, cword);
} else if (flags & WF_ONECAP) {
// Make the first letter upper-case
- onecap_copy(fword, (char *)cword, true);
+ onecap_copy(fword, cword, true);
} else {
// Use goodword as-is.
STRCPY(cword, fword);
@@ -2720,9 +2729,9 @@ char *eval_soundfold(const char *const word)
langp_T *const lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
if (!GA_EMPTY(&lp->lp_slang->sl_sal)) {
// soundfold the word
- char_u sound[MAXWLEN];
- spell_soundfold(lp->lp_slang, (char *)word, false, (char *)sound);
- return xstrdup((const char *)sound);
+ char sound[MAXWLEN];
+ spell_soundfold(lp->lp_slang, (char *)word, false, sound);
+ return xstrdup(sound);
}
}
}
@@ -2750,7 +2759,7 @@ void spell_soundfold(slang_T *slang, char *inword, bool folded, char *res)
{
if (slang->sl_sofo) {
// SOFOFROM and SOFOTO used
- spell_soundfold_sofo(slang, (char_u *)inword, (char_u *)res);
+ spell_soundfold_sofo(slang, inword, res);
} else {
char fword[MAXWLEN];
char *word;
@@ -2758,17 +2767,17 @@ void spell_soundfold(slang_T *slang, char *inword, bool folded, char *res)
if (folded) {
word = inword;
} else {
- (void)spell_casefold(curwin, (char_u *)inword, (int)strlen(inword), (char_u *)fword, MAXWLEN);
+ (void)spell_casefold(curwin, inword, (int)strlen(inword), fword, MAXWLEN);
word = fword;
}
- spell_soundfold_wsal(slang, (char_u *)word, (char_u *)res);
+ spell_soundfold_wsal(slang, word, res);
}
}
// Perform sound folding of "inword" into "res" according to SOFOFROM and
// SOFOTO lines.
-static void spell_soundfold_sofo(slang_T *slang, char_u *inword, char_u *res)
+static void spell_soundfold_sofo(slang_T *slang, char *inword, char *res)
{
int ri = 0;
@@ -2776,8 +2785,8 @@ static void spell_soundfold_sofo(slang_T *slang, char_u *inword, char_u *res)
// The sl_sal_first[] table contains the translation for chars up to
// 255, sl_sal the rest.
- for (char_u *s = inword; *s != NUL;) {
- int c = mb_cptr2char_adv((const char_u **)&s);
+ for (char *s = inword; *s != NUL;) {
+ int c = mb_cptr2char_adv((const char **)&s);
if (utf_class(c) == 0) {
c = ' ';
} else if (c < 256) {
@@ -2802,7 +2811,7 @@ static void spell_soundfold_sofo(slang_T *slang, char_u *inword, char_u *res)
}
if (c != NUL && c != prevc) {
- ri += utf_char2bytes(c, (char *)res + ri);
+ ri += utf_char2bytes(c, res + ri);
if (ri + MB_MAXBYTES > MAXWLEN) {
break;
}
@@ -2815,7 +2824,7 @@ static void spell_soundfold_sofo(slang_T *slang, char_u *inword, char_u *res)
// Turn "inword" into its sound-a-like equivalent in "res[MAXWLEN]".
// Multi-byte version of spell_soundfold().
-static void spell_soundfold_wsal(slang_T *slang, const char_u *inword, char_u *res)
+static void spell_soundfold_wsal(slang_T *slang, const char *inword, char *res)
{
salitem_T *smp = (salitem_T *)slang->sl_sal.ga_data;
int word[MAXWLEN] = { 0 };
@@ -2837,8 +2846,8 @@ static void spell_soundfold_wsal(slang_T *slang, const char_u *inword, char_u *r
// Remove accents, if wanted. We actually remove all non-word characters.
// But keep white space.
int wordlen = 0;
- for (const char_u *s = inword; *s != NUL;) {
- const char_u *t = s;
+ for (const char *s = (char *)inword; *s != NUL;) {
+ const char_u *t = (char_u *)s;
int c = mb_cptr2char_adv(&s);
if (slang->sl_rem_accents) {
if (utf_class(c) == 0) {
@@ -2849,7 +2858,7 @@ static void spell_soundfold_wsal(slang_T *slang, const char_u *inword, char_u *r
did_white = true;
} else {
did_white = false;
- if (!spell_iswordp_nmw(t, curwin)) {
+ if (!spell_iswordp_nmw((char *)t, curwin)) {
continue;
}
}
@@ -2906,7 +2915,7 @@ static void spell_soundfold_wsal(slang_T *slang, const char_u *inword, char_u *r
}
k++;
}
- char_u *s = smp[n].sm_rules;
+ char_u *s = (char_u *)smp[n].sm_rules;
pri = 5; // default priority
p0 = *s;
@@ -2983,7 +2992,7 @@ static void spell_soundfold_wsal(slang_T *slang, const char_u *inword, char_u *r
}
p0 = 5;
- s = smp[n0].sm_rules;
+ s = (char_u *)smp[n0].sm_rules;
while (*s == '-') {
// "k0" gets NOT reduced because
// "if (k0 == k)"
@@ -3024,7 +3033,7 @@ static void spell_soundfold_wsal(slang_T *slang, const char_u *inword, char_u *r
// replace string
ws = smp[n].sm_to_w;
- s = smp[n].sm_rules;
+ s = (char_u *)smp[n].sm_rules;
p0 = (vim_strchr((char *)s, '<') != NULL) ? 1 : 0;
if (p0 == 1 && z == 0) {
// rule with '<' is used
@@ -3102,7 +3111,7 @@ static void spell_soundfold_wsal(slang_T *slang, const char_u *inword, char_u *r
// Convert wide characters in "wres" to a multi-byte string in "res".
int l = 0;
for (int n = 0; n < reslen; n++) {
- l += utf_char2bytes(wres[n], (char *)res + l);
+ l += utf_char2bytes(wres[n], res + l);
if (l + MB_MAXBYTES > MAXWLEN) {
break;
}
@@ -3204,7 +3213,7 @@ void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg)
if (ic) {
dumpflags |= DUMPFLAG_ICASE;
} else {
- n = captype((char_u *)pat, NULL);
+ n = captype(pat, NULL);
if (n == WF_ONECAP) {
dumpflags |= DUMPFLAG_ONECAP;
} else if (n == WF_ALLCAP
@@ -3218,7 +3227,7 @@ void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg)
// regions or none at all.
for (int lpi = 0; lpi < curwin->w_s->b_langp.ga_len; lpi++) {
lp = LANGP_ENTRY(curwin->w_s->b_langp, lpi);
- p = (char *)lp->lp_slang->sl_regions;
+ p = lp->lp_slang->sl_regions;
if (p[0] != 0) {
if (region_names == NULL) { // first language with regions
region_names = p;
@@ -3264,11 +3273,11 @@ void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg)
for (int round = 1; round <= 2; round++) {
if (round == 1) {
dumpflags &= ~DUMPFLAG_KEEPCASE;
- byts = (char *)slang->sl_fbyts;
+ byts = slang->sl_fbyts;
idxs = slang->sl_fidxs;
} else {
dumpflags |= DUMPFLAG_KEEPCASE;
- byts = (char *)slang->sl_kbyts;
+ byts = slang->sl_kbyts;
idxs = slang->sl_kidxs;
}
if (byts == NULL) {
@@ -3319,7 +3328,7 @@ void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg)
// Apply the prefix, if there is one.
if (c != 0) {
- lnum = dump_prefixes(slang, word, (char_u *)pat, dir,
+ lnum = dump_prefixes(slang, word, pat, dir,
dumpflags, flags, lnum);
}
}
@@ -3337,7 +3346,7 @@ void spell_dump_compl(char *pat, int ic, Direction *dir, int dumpflags_arg)
// ignore case...
assert(depth >= 0);
if (depth <= patlen
- && mb_strnicmp((char *)word, pat, (size_t)depth) != 0) {
+ && mb_strnicmp(word, pat, (size_t)depth) != 0) {
depth--;
}
}
@@ -3367,12 +3376,12 @@ static void dump_word(slang_T *slang, char *word, char *pat, Direction *dir, int
if ((dumpflags & DUMPFLAG_KEEPCASE) == 0 && (flags & WF_CAPMASK) != 0) {
// Need to fix case according to "flags".
- make_case_word((char_u *)word, (char_u *)cword, flags);
+ make_case_word(word, cword, flags);
p = cword;
} else {
p = word;
if ((dumpflags & DUMPFLAG_KEEPCASE)
- && ((captype((char_u *)word, NULL) & WF_KEEPCAP) == 0
+ && ((captype(word, NULL) & WF_KEEPCAP) == 0
|| (flags & WF_FIXCAP) != 0)) {
keepcap = true;
}
@@ -3436,8 +3445,8 @@ static void dump_word(slang_T *slang, char *word, char *pat, Direction *dir, int
/// @param flags flags with prefix ID
///
/// @return the updated line number.
-static linenr_T dump_prefixes(slang_T *slang, char *word, char_u *pat, Direction *dir,
- int dumpflags, int flags, linenr_T startlnum)
+static linenr_T dump_prefixes(slang_T *slang, char *word, char *pat, Direction *dir, int dumpflags,
+ int flags, linenr_T startlnum)
{
idx_T arridx[MAXWLEN];
int curi[MAXWLEN];
@@ -3450,11 +3459,11 @@ static linenr_T dump_prefixes(slang_T *slang, char *word, char_u *pat, Direction
// upper-case letter in word_up[].
int c = utf_ptr2char(word);
if (SPELL_TOUPPER(c) != c) {
- onecap_copy((char_u *)word, (char *)word_up, true);
+ onecap_copy(word, word_up, true);
has_word_up = true;
}
- char_u *byts = slang->sl_pbyts;
+ char_u *byts = (char_u *)slang->sl_pbyts;
idx_T *idxs = slang->sl_pidxs;
if (byts != NULL) { // array not is empty
// Loop over all prefixes, building them byte-by-byte in prefix[].
@@ -3484,10 +3493,10 @@ static linenr_T dump_prefixes(slang_T *slang, char *word, char_u *pat, Direction
}
curi[depth] += i - 1;
- c = valid_word_prefix(i, n, flags, (char_u *)word, slang, false);
+ c = valid_word_prefix(i, n, flags, word, slang, false);
if (c != 0) {
xstrlcpy(prefix + depth, word, (size_t)(MAXWLEN - depth));
- dump_word(slang, (char *)prefix, (char *)pat, dir, dumpflags,
+ dump_word(slang, prefix, pat, dir, dumpflags,
(c & WF_RAREPFX) ? (flags | WF_RARE) : flags, lnum);
if (lnum != 0) {
lnum++;
@@ -3498,11 +3507,10 @@ static linenr_T dump_prefixes(slang_T *slang, char *word, char_u *pat, Direction
// first letter is upper-case, but only if the prefix has
// a condition.
if (has_word_up) {
- c = valid_word_prefix(i, n, flags, (char_u *)word_up, slang,
- true);
+ c = valid_word_prefix(i, n, flags, word_up, slang, true);
if (c != 0) {
xstrlcpy(prefix + depth, word_up, (size_t)(MAXWLEN - depth));
- dump_word(slang, (char *)prefix, (char *)pat, dir, dumpflags,
+ dump_word(slang, prefix, pat, dir, dumpflags,
(c & WF_RAREPFX) ? (flags | WF_RARE) : flags, lnum);
if (lnum != 0) {
lnum++;
@@ -3524,9 +3532,9 @@ static linenr_T dump_prefixes(slang_T *slang, char *word, char_u *pat, Direction
// Move "p" to the end of word "start".
// Uses the spell-checking word characters.
-char_u *spell_to_word_end(char_u *start, win_T *win)
+char *spell_to_word_end(char *start, win_T *win)
{
- char_u *p = start;
+ char *p = start;
while (*p != NUL && spell_iswordp(p, win)) {
MB_PTR_ADV(p);
@@ -3545,8 +3553,8 @@ int spell_word_start(int startcol)
return startcol;
}
- char_u *line = (char_u *)get_cursor_line_ptr();
- char_u *p;
+ char *line = get_cursor_line_ptr();
+ char *p;
// Find a word character before "startcol".
for (p = line + startcol; p > line;) {
@@ -3588,7 +3596,7 @@ int expand_spelling(linenr_T lnum, char *pat, char ***matchp)
{
garray_T ga;
- spell_suggest_list(&ga, (char_u *)pat, 100, spell_expand_need_cap, true);
+ spell_suggest_list(&ga, pat, 100, spell_expand_need_cap, true);
*matchp = ga.ga_data;
return ga.ga_len;
}
@@ -3624,15 +3632,16 @@ char *did_set_spell_option(bool is_spellfile)
}
}
- if (errmsg == NULL) {
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_buffer == curbuf && wp->w_p_spell) {
- errmsg = did_set_spelllang(wp);
- break;
- }
- }
+ if (errmsg != NULL) {
+ return errmsg;
}
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ if (wp->w_buffer == curbuf && wp->w_p_spell) {
+ errmsg = did_set_spelllang(wp);
+ break;
+ }
+ }
return errmsg;
}
diff --git a/src/nvim/spell_defs.h b/src/nvim/spell_defs.h
index 4d146a1706..726af7d698 100644
--- a/src/nvim/spell_defs.h
+++ b/src/nvim/spell_defs.h
@@ -80,11 +80,11 @@ typedef struct fromto_S {
// The info is split for quick processing by spell_soundfold().
// Note that "sm_oneof" and "sm_rules" point into sm_lead.
typedef struct salitem_S {
- char_u *sm_lead; // leading letters
- int sm_leadlen; // length of "sm_lead"
- char_u *sm_oneof; // letters from () or NULL
- char_u *sm_rules; // rules like ^, $, priority
- char_u *sm_to; // replacement.
+ char *sm_lead; // leading letters
+ int sm_leadlen; // length of "sm_lead"
+ char_u *sm_oneof; // letters from () or NULL
+ char *sm_rules; // rules like ^, $, priority
+ char *sm_to; // replacement.
int *sm_lead_w; // wide character copy of "sm_lead"
int *sm_oneof_w; // wide character copy of "sm_oneof"
int *sm_to_w; // wide character copy of "sm_to"
@@ -119,17 +119,17 @@ struct slang_S {
char *sl_fname; // name of .spl file
bool sl_add; // true if it's a .add file.
- char_u *sl_fbyts; // case-folded word bytes
+ char *sl_fbyts; // case-folded word bytes
long sl_fbyts_len; // length of sl_fbyts
idx_T *sl_fidxs; // case-folded word indexes
- char_u *sl_kbyts; // keep-case word bytes
+ char *sl_kbyts; // keep-case word bytes
idx_T *sl_kidxs; // keep-case word indexes
- char_u *sl_pbyts; // prefix tree word bytes
+ char *sl_pbyts; // prefix tree word bytes
idx_T *sl_pidxs; // prefix tree word indexes
char_u *sl_info; // infotext string or NULL
- char_u sl_regions[MAXREGIONS * 2 + 1];
+ char sl_regions[MAXREGIONS * 2 + 1];
// table with up to 8 region names plus NUL
char_u *sl_midword; // MIDWORD string or NULL
@@ -143,9 +143,9 @@ struct slang_S {
garray_T sl_comppat; // CHECKCOMPOUNDPATTERN items
regprog_T *sl_compprog; // COMPOUNDRULE turned into a regexp progrm
// (NULL when no compounding)
- char_u *sl_comprules; // all COMPOUNDRULE concatenated (or NULL)
- char_u *sl_compstartflags; // flags for first compound word
- char_u *sl_compallflags; // all flags for compound words
+ uint8_t *sl_comprules; // all COMPOUNDRULE concatenated (or NULL)
+ uint8_t *sl_compstartflags; // flags for first compound word
+ uint8_t *sl_compallflags; // all flags for compound words
bool sl_nobreak; // When true: no spaces between words
char_u *sl_syllable; // SYLLABLE repeatable chars or NULL
garray_T sl_syl_items; // syllable items
@@ -172,7 +172,7 @@ struct slang_S {
// Info from the .sug file. Loaded on demand.
time_t sl_sugtime; // timestamp for .sug file
- char_u *sl_sbyts; // soundfolded word bytes
+ char *sl_sbyts; // soundfolded word bytes
idx_T *sl_sidxs; // soundfolded word indexes
buf_T *sl_sugbuf; // buffer with word number table
bool sl_sugloaded; // true when .sug file was loaded or failed to
@@ -227,7 +227,7 @@ typedef struct {
extern slang_T *first_lang;
// file used for "zG" and "zW"
-extern char_u *int_wordlist;
+extern char *int_wordlist;
extern spelltab_T spelltab;
extern int did_set_spelltab;
diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c
index e6257aeca1..7b124ae6b6 100644
--- a/src/nvim/spellfile.c
+++ b/src/nvim/spellfile.c
@@ -270,10 +270,6 @@
#include "nvim/undo.h"
#include "nvim/vim.h"
-#ifndef UNIX // it's in os/unix_defs.h for Unix
-# include <time.h>
-#endif
-
// Special byte values for <byte>. Some are only used in the tree for
// postponed prefixes, some only in the other trees. This is a bit messy...
enum {
@@ -336,7 +332,7 @@ static char *msg_compressing = N_("Compressing word tree...");
// and .dic file.
// Main structure to store the contents of a ".aff" file.
typedef struct afffile_S {
- char_u *af_enc; // "SET", normalized, alloc'ed string or NULL
+ char *af_enc; // "SET", normalized, alloc'ed string or NULL
int af_flagtype; // AFT_CHAR, AFT_LONG, AFT_NUM or AFT_CAPLONG
unsigned af_rare; // RARE ID for rare word
unsigned af_keepcase; // KEEPCASE ID for keep-case word
@@ -364,12 +360,12 @@ typedef struct afffile_S {
typedef struct affentry_S affentry_T;
// Affix entry from ".aff" file. Used for prefixes and suffixes.
struct affentry_S {
- affentry_T *ae_next; // next affix with same name/number
- char *ae_chop; // text to chop off basic word (can be NULL)
- char *ae_add; // text to add to basic word (can be NULL)
- char_u *ae_flags; // flags on the affix (can be NULL)
- char_u *ae_cond; // condition (NULL for ".")
- regprog_T *ae_prog; // regexp program for ae_cond or NULL
+ affentry_T *ae_next; // next affix with same name/number
+ char *ae_chop; // text to chop off basic word (can be NULL)
+ char *ae_add; // text to add to basic word (can be NULL)
+ char *ae_flags; // flags on the affix (can be NULL)
+ char *ae_cond; // condition (NULL for ".")
+ regprog_T *ae_prog; // regexp program for ae_cond or NULL
char ae_compforbid; // COMPOUNDFORBIDFLAG found
char ae_comppermit; // COMPOUNDPERMITFLAG found
};
@@ -724,7 +720,7 @@ slang_T *spell_load_file(char *fname, char *lang, slang_T *old_lp, bool silent)
if (p == NULL) {
goto endFAIL;
}
- set_map_str(lp, (char_u *)p);
+ set_map_str(lp, p);
xfree(p);
break;
@@ -1004,8 +1000,8 @@ someerror:
// Need to put word counts in the word tries, so that we can find
// a word by its number.
- tree_count_words(slang->sl_fbyts, slang->sl_fidxs);
- tree_count_words(slang->sl_sbyts, slang->sl_sidxs);
+ tree_count_words((char_u *)slang->sl_fbyts, slang->sl_fidxs);
+ tree_count_words((char_u *)slang->sl_sbyts, slang->sl_sidxs);
nextone:
if (fd != NULL) {
@@ -1054,7 +1050,7 @@ static int read_region_section(FILE *fd, slang_T *lp, int len)
if (len > MAXREGIONS * 2) {
return SP_FORMERROR;
}
- SPELL_READ_NONNUL_BYTES((char *)lp->sl_regions, (size_t)len, fd,; ); // NOLINT(whitespace/parens)
+ SPELL_READ_NONNUL_BYTES(lp->sl_regions, (size_t)len, fd,; ); // NOLINT(whitespace/parens)
lp->sl_regions[len] = NUL;
return 0;
}
@@ -1064,12 +1060,12 @@ static int read_region_section(FILE *fd, slang_T *lp, int len)
// Return SP_*ERROR flags.
static int read_charflags_section(FILE *fd)
{
- char_u *flags;
+ char *flags;
char_u *fol;
int flagslen, follen;
// <charflagslen> <charflags>
- flags = read_cnt_string(fd, 1, &flagslen);
+ flags = (char *)read_cnt_string(fd, 1, &flagslen);
if (flagslen < 0) {
return flagslen;
}
@@ -1083,7 +1079,7 @@ static int read_charflags_section(FILE *fd)
// Set the word-char flags and fill SPELL_ISUPPER() table.
if (flags != NULL && fol != NULL) {
- set_spell_charflags(flags, flagslen, fol);
+ set_spell_charflags((char_u *)flags, flagslen, (char *)fol);
}
xfree(flags);
@@ -1219,7 +1215,7 @@ static int read_sal_section(FILE *fd, slang_T *slang)
return SP_TRUNCERROR;
}
p = xmalloc((size_t)ccnt + 2);
- smp->sm_lead = p;
+ smp->sm_lead = (char *)p;
// Read up to the first special char into sm_lead.
int i = 0;
@@ -1230,7 +1226,7 @@ static int read_sal_section(FILE *fd, slang_T *slang)
}
*p++ = (char_u)c;
}
- smp->sm_leadlen = (int)(p - smp->sm_lead);
+ smp->sm_leadlen = (int)(p - (char_u *)smp->sm_lead);
*p++ = NUL;
// Put (abc) chars in sm_oneof, if any.
@@ -1252,7 +1248,7 @@ static int read_sal_section(FILE *fd, slang_T *slang)
}
// Any following chars go in sm_rules.
- smp->sm_rules = p;
+ smp->sm_rules = (char *)p;
if (i < ccnt) {
// store the char we got while checking for end of sm_lead
*p++ = (char_u)c;
@@ -1267,7 +1263,7 @@ static int read_sal_section(FILE *fd, slang_T *slang)
*p++ = NUL;
// <saltolen> <salto>
- smp->sm_to = read_cnt_string(fd, 1, &ccnt);
+ smp->sm_to = (char *)read_cnt_string(fd, 1, &ccnt);
if (ccnt < 0) {
xfree(smp->sm_lead);
return ccnt;
@@ -1275,11 +1271,11 @@ static int read_sal_section(FILE *fd, slang_T *slang)
// convert the multi-byte strings to wide char strings
smp->sm_lead_w = mb_str2wide(smp->sm_lead);
- smp->sm_leadlen = mb_charlen((char *)smp->sm_lead);
+ smp->sm_leadlen = mb_charlen(smp->sm_lead);
if (smp->sm_oneof == NULL) {
smp->sm_oneof_w = NULL;
} else {
- smp->sm_oneof_w = mb_str2wide(smp->sm_oneof);
+ smp->sm_oneof_w = mb_str2wide((char *)smp->sm_oneof);
}
if (smp->sm_to == NULL) {
smp->sm_to_w = NULL;
@@ -1294,12 +1290,12 @@ static int read_sal_section(FILE *fd, slang_T *slang)
smp = &((salitem_T *)gap->ga_data)[gap->ga_len];
p = xmalloc(1);
p[0] = NUL;
- smp->sm_lead = p;
+ smp->sm_lead = (char *)p;
smp->sm_lead_w = mb_str2wide(smp->sm_lead);
smp->sm_leadlen = 0;
smp->sm_oneof = NULL;
smp->sm_oneof_w = NULL;
- smp->sm_rules = p;
+ smp->sm_rules = (char *)p;
smp->sm_to = NULL;
smp->sm_to_w = NULL;
gap->ga_len++;
@@ -1348,19 +1344,19 @@ static int read_words_section(FILE *fd, slang_T *lp, int len)
static int read_sofo_section(FILE *fd, slang_T *slang)
{
int cnt;
- char_u *from, *to;
+ char *from, *to;
int res;
slang->sl_sofo = true;
// <sofofromlen> <sofofrom>
- from = read_cnt_string(fd, 2, &cnt);
+ from = (char *)read_cnt_string(fd, 2, &cnt);
if (cnt < 0) {
return cnt;
}
// <sofotolen> <sofoto>
- to = read_cnt_string(fd, 2, &cnt);
+ to = (char *)read_cnt_string(fd, 2, &cnt);
if (cnt < 0) {
xfree(from);
return cnt;
@@ -1430,7 +1426,7 @@ static int read_compound(FILE *fd, slang_T *slang, int len)
return SP_TRUNCERROR;
}
todo -= 2;
- ga_init(gap, sizeof(char_u *), c);
+ ga_init(gap, sizeof(char *), c);
ga_grow(gap, c);
while (--c >= 0) {
((char **)(gap->ga_data))[gap->ga_len++] = (char *)read_cnt_string(fd, 1, &cnt);
@@ -1451,25 +1447,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;
- char_u *pat = xmalloc((size_t)c);
+ char *pat = xmalloc((size_t)c);
// We also need a list of all flags that can appear at the start and one
// for all flags.
- char_u *cp = xmalloc((size_t)todo + 1);
+ uint8_t *cp = xmalloc((size_t)todo + 1);
slang->sl_compstartflags = cp;
*cp = NUL;
- char_u *ap = xmalloc((size_t)todo + 1);
+ uint8_t *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.
- char_u *crp = xmalloc((size_t)todo + 1);
+ uint8_t *crp = xmalloc((size_t)todo + 1);
slang->sl_comprules = crp;
- char_u *pp = pat;
+ char_u *pp = (char_u *)pat;
*pp++ = '^';
*pp++ = '\\';
*pp++ = '(';
@@ -1538,7 +1534,7 @@ static int read_compound(FILE *fd, slang_T *slang, int len)
*crp = NUL;
}
- slang->sl_compprog = vim_regcomp((char *)pat, RE_MAGIC + RE_STRING + RE_STRICT);
+ slang->sl_compprog = vim_regcomp(pat, RE_MAGIC + RE_STRING + RE_STRICT);
xfree(pat);
if (slang->sl_compprog == NULL) {
return SP_FORMERROR;
@@ -1549,10 +1545,10 @@ static int read_compound(FILE *fd, slang_T *slang, int len)
// Set the SOFOFROM and SOFOTO items in language "lp".
// Returns SP_*ERROR flags when there is something wrong.
-static int set_sofo(slang_T *lp, char_u *from, char_u *to)
+static int set_sofo(slang_T *lp, char *from, char *to)
{
- char_u *s;
- char_u *p;
+ char *s;
+ char *p;
// Use "sl_sal" as an array with 256 pointers to a list of wide
// characters. The index is the low byte of the character.
@@ -1567,7 +1563,7 @@ static int set_sofo(slang_T *lp, char_u *from, char_u *to)
// First count the number of items for each list. Temporarily use
// sl_sal_first[] for this.
for (p = from, s = to; *p != NUL && *s != NUL;) {
- const int c = mb_cptr2char_adv((const char_u **)&p);
+ const int c = mb_cptr2char_adv((const char **)&p);
MB_CPTR_ADV(s);
if (c >= 256) {
lp->sl_sal_first[c & 0xff]++;
@@ -1590,8 +1586,8 @@ static int set_sofo(slang_T *lp, char_u *from, char_u *to)
// list.
memset(lp->sl_sal_first, 0, sizeof(salfirst_T) * 256);
for (p = from, s = to; *p != NUL && *s != NUL;) {
- const int c = mb_cptr2char_adv((const char_u **)&p);
- const int i = mb_cptr2char_adv((const char_u **)&s);
+ const int c = mb_cptr2char_adv((const char **)&p);
+ const int i = mb_cptr2char_adv((const char **)&s);
if (c >= 256) {
// Append the from-to chars at the end of the list with
// the low byte.
@@ -1660,13 +1656,13 @@ static void set_sal_first(slang_T *lp)
// Turn a multi-byte string into a wide character string.
// Return it in allocated memory.
-static int *mb_str2wide(char_u *s)
+static int *mb_str2wide(char *s)
{
int i = 0;
- int *res = xmalloc(((size_t)mb_charlen((char *)s) + 1) * sizeof(int));
- for (char_u *p = s; *p != NUL;) {
- res[i++] = mb_ptr2char_adv((const char_u **)&p);
+ int *res = xmalloc(((size_t)mb_charlen(s) + 1) * sizeof(int));
+ for (char *p = s; *p != NUL;) {
+ res[i++] = mb_ptr2char_adv((const char **)&p);
}
res[i] = NUL;
@@ -1681,12 +1677,12 @@ static int *mb_str2wide(char_u *s)
/// @param prefixcnt when "prefixtree" is true: prefix count
///
/// @return zero when OK, SP_ value for an error.
-static int spell_read_tree(FILE *fd, char_u **bytsp, long *bytsp_len, idx_T **idxsp,
- bool prefixtree, int prefixcnt)
+static int spell_read_tree(FILE *fd, char **bytsp, long *bytsp_len, idx_T **idxsp, bool prefixtree,
+ int prefixcnt)
FUNC_ATTR_NONNULL_ARG(1, 2, 4)
{
int idx;
- char_u *bp;
+ char *bp;
idx_T *ip;
// The tree size was computed when writing the file, so that we can
@@ -1699,23 +1695,25 @@ static int spell_read_tree(FILE *fd, char_u **bytsp, long *bytsp_len, idx_T **id
// Invalid length, multiply with sizeof(int) would overflow.
return SP_FORMERROR;
}
- if (len > 0) {
- // Allocate the byte array.
- bp = xmalloc((size_t)len);
- *bytsp = bp;
- if (bytsp_len != NULL) {
- *bytsp_len = len;
- }
+ if (len <= 0) {
+ return 0;
+ }
- // Allocate the index array.
- ip = xcalloc((size_t)len, sizeof(*ip));
- *idxsp = ip;
+ // Allocate the byte array.
+ bp = xmalloc((size_t)len);
+ *bytsp = bp;
+ if (bytsp_len != NULL) {
+ *bytsp_len = len;
+ }
- // Recursively read the tree and store it in the array.
- idx = read_tree_node(fd, bp, ip, (int)len, 0, prefixtree, prefixcnt);
- if (idx < 0) {
- return idx;
- }
+ // Allocate the index array.
+ ip = xcalloc((size_t)len, sizeof(*ip));
+ *idxsp = ip;
+
+ // Recursively read the tree and store it in the array.
+ idx = read_tree_node(fd, (char_u *)bp, ip, (int)len, 0, prefixtree, prefixcnt);
+ if (idx < 0) {
+ return idx;
}
return 0;
}
@@ -1839,15 +1837,15 @@ static idx_T read_tree_node(FILE *fd, char_u *byts, idx_T *idxs, int maxidx, idx
/// Reload the spell file "fname" if it's loaded.
///
/// @param added_word invoked through "zg"
-static void spell_reload_one(char_u *fname, bool added_word)
+static void spell_reload_one(char *fname, bool added_word)
{
slang_T *slang;
bool didit = false;
for (slang = first_lang; slang != NULL; slang = slang->sl_next) {
- if (path_full_compare((char *)fname, slang->sl_fname, false, true) == kEqualFiles) {
+ if (path_full_compare(fname, slang->sl_fname, false, true) == kEqualFiles) {
slang_clear(slang);
- if (spell_load_file((char *)fname, NULL, slang, false) == NULL) {
+ if (spell_load_file(fname, NULL, slang, false) == NULL) {
// reloading failed, clear the language
slang_clear(slang);
}
@@ -2007,26 +2005,27 @@ static void spell_print_node(wordnode_T *node, int depth)
static void spell_print_tree(wordnode_T *root)
{
- if (root != NULL) {
- // Clear the "wn_u1.index" fields, used to remember what has been
- // done.
- spell_clear_flags(root);
-
- // Recursively print the tree.
- spell_print_node(root, 0);
+ if (root == NULL) {
+ return;
}
+
+ // Clear the "wn_u1.index" fields, used to remember what has been done.
+ spell_clear_flags(root);
+
+ // Recursively print the tree.
+ spell_print_node(root, 0);
}
#endif // SPELL_PRINTTREE
// Reads the affix file "fname".
// Returns an afffile_T, NULL for complete failure.
-static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
+static afffile_T *spell_read_aff(spellinfo_T *spin, char *fname)
{
FILE *fd;
- char_u rline[MAXLINELEN];
- char_u *line;
- char_u *pc = NULL;
+ char rline[MAXLINELEN];
+ char *line;
+ char *pc = NULL;
#define MAXITEMCNT 30
char *(items[MAXITEMCNT]);
int itemcnt;
@@ -2052,13 +2051,13 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
int compmax = 0; // COMPOUNDWORDMAX value
char *compflags = NULL; // COMPOUNDFLAG and COMPOUNDRULE
// concatenated
- char_u *midword = NULL; // MIDWORD value
- char_u *syllable = NULL; // SYLLABLE value
- char_u *sofofrom = NULL; // SOFOFROM value
- char_u *sofoto = NULL; // SOFOTO value
+ char *midword = NULL; // MIDWORD value
+ char *syllable = NULL; // SYLLABLE value
+ char *sofofrom = NULL; // SOFOFROM value
+ char *sofoto = NULL; // SOFOTO value
// Open the file.
- fd = os_fopen((char *)fname, "r");
+ fd = os_fopen(fname, "r");
if (fd == NULL) {
semsg(_(e_notopen), fname);
return NULL;
@@ -2086,7 +2085,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
hash_init(&aff->af_comp);
// Read all the lines in the file one by one.
- while (!vim_fgets((char *)rline, MAXLINELEN, fd) && !got_int) {
+ while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int) {
line_breakcheck();
lnum++;
@@ -2098,7 +2097,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
// Convert from "SET" to 'encoding' when needed.
xfree(pc);
if (spin->si_conv.vc_type != CONV_NONE) {
- pc = (char_u *)string_convert(&spin->si_conv, (char *)rline, NULL);
+ pc = string_convert(&spin->si_conv, rline, NULL);
if (pc == NULL) {
smsg(_("Conversion failure for word in %s line %d: %s"),
fname, lnum, rline);
@@ -2113,7 +2112,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
// Split the line up in white separated items. Put a NUL after each
// item.
itemcnt = 0;
- for (p = (char *)line;;) {
+ for (p = line;;) {
while (*p != NUL && (uint8_t)(*p) <= ' ') { // skip white space and CR/NL
p++;
}
@@ -2144,9 +2143,9 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
if (itemcnt > 0) {
if (is_aff_rule(items, itemcnt, "SET", 2) && aff->af_enc == NULL) {
// Setup for conversion from "ENC" to 'encoding'.
- aff->af_enc = (char_u *)enc_canonize((char *)items[1]);
+ aff->af_enc = enc_canonize((char *)items[1]);
if (!spin->si_ascii
- && convert_setup(&spin->si_conv, (char *)aff->af_enc, p_enc) == FAIL) {
+ && convert_setup(&spin->si_conv, aff->af_enc, p_enc) == FAIL) {
smsg(_("Conversion in %s not supported: from %s to %s"),
fname, aff->af_enc, p_enc);
}
@@ -2191,57 +2190,47 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
STRCAT(p, items[1]);
spin->si_info = p;
} else if (is_aff_rule(items, itemcnt, "MIDWORD", 2) && midword == NULL) {
- midword = (char_u *)getroom_save(spin, items[1]);
+ midword = getroom_save(spin, items[1]);
} else if (is_aff_rule(items, itemcnt, "TRY", 2)) {
// ignored, we look in the tree for what chars may appear
} else if ((is_aff_rule(items, itemcnt, "RAR", 2) // TODO(vim): remove "RAR" later
|| is_aff_rule(items, itemcnt, "RARE", 2))
&& aff->af_rare == 0) {
- aff->af_rare = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ aff->af_rare = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
} else if ((is_aff_rule(items, itemcnt, "KEP", 2) // TODO(vim): remove "KEP" later
|| is_aff_rule(items, itemcnt, "KEEPCASE", 2))
&& aff->af_keepcase == 0) {
- aff->af_keepcase = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ aff->af_keepcase = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
} else if ((is_aff_rule(items, itemcnt, "BAD", 2)
|| is_aff_rule(items, itemcnt, "FORBIDDENWORD", 2))
&& aff->af_bad == 0) {
- aff->af_bad = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ aff->af_bad = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
} else if (is_aff_rule(items, itemcnt, "NEEDAFFIX", 2)
&& aff->af_needaffix == 0) {
- aff->af_needaffix = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ aff->af_needaffix = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
} else if (is_aff_rule(items, itemcnt, "CIRCUMFIX", 2)
&& aff->af_circumfix == 0) {
- aff->af_circumfix = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ aff->af_circumfix = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
} else if (is_aff_rule(items, itemcnt, "NOSUGGEST", 2)
&& aff->af_nosuggest == 0) {
- aff->af_nosuggest = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ aff->af_nosuggest = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
} else if ((is_aff_rule(items, itemcnt, "NEEDCOMPOUND", 2)
|| is_aff_rule(items, itemcnt, "ONLYINCOMPOUND", 2))
&& aff->af_needcomp == 0) {
- aff->af_needcomp = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ aff->af_needcomp = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
} else if (is_aff_rule(items, itemcnt, "COMPOUNDROOT", 2)
&& aff->af_comproot == 0) {
- aff->af_comproot = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ aff->af_comproot = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
} else if (is_aff_rule(items, itemcnt, "COMPOUNDFORBIDFLAG", 2)
&& aff->af_compforbid == 0) {
- aff->af_compforbid = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ aff->af_compforbid = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
if (aff->af_pref.ht_used > 0) {
smsg(_("Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in %s line %d"),
fname, lnum);
}
} else if (is_aff_rule(items, itemcnt, "COMPOUNDPERMITFLAG", 2)
&& aff->af_comppermit == 0) {
- aff->af_comppermit = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ aff->af_comppermit = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
if (aff->af_pref.ht_used > 0) {
smsg(_("Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in %s line %d"),
fname, lnum);
@@ -2330,7 +2319,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
}
} else if (is_aff_rule(items, itemcnt, "SYLLABLE", 2)
&& syllable == NULL) {
- syllable = (char_u *)getroom_save(spin, items[1]);
+ syllable = getroom_save(spin, items[1]);
} else if (is_aff_rule(items, itemcnt, "NOBREAK", 1)) {
spin->si_nobreak = true;
} else if (is_aff_rule(items, itemcnt, "NOSPLITSUGS", 1)) {
@@ -2375,8 +2364,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
} else {
// New affix letter.
cur_aff = getroom(spin, sizeof(*cur_aff), true);
- cur_aff->ah_flag = affitem2flag(aff->af_flagtype, (char_u *)items[1],
- fname, lnum);
+ cur_aff->ah_flag = affitem2flag(aff->af_flagtype, items[1], fname, lnum);
if (cur_aff->ah_flag == 0 || strlen(items[1]) >= AH_KEY_LEN) {
break;
}
@@ -2469,7 +2457,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
aff_entry->ae_add = getroom_save(spin, items[3]);
// Recognize flags on the affix: abcd/XYZ
- aff_entry->ae_flags = (char_u *)vim_strchr(aff_entry->ae_add, '/');
+ aff_entry->ae_flags = vim_strchr(aff_entry->ae_add, '/');
if (aff_entry->ae_flags != NULL) {
*aff_entry->ae_flags++ = NUL;
aff_process_flags(aff, aff_entry);
@@ -2484,15 +2472,15 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
cur_aff->ah_first = aff_entry;
if (strcmp(items[4], ".") != 0) {
- char_u buf[MAXLINELEN];
+ char buf[MAXLINELEN];
- aff_entry->ae_cond = (char_u *)getroom_save(spin, items[4]);
+ aff_entry->ae_cond = getroom_save(spin, items[4]);
if (*items[0] == 'P') {
- sprintf((char *)buf, "^%s", items[4]); // NOLINT(runtime/printf)
+ sprintf(buf, "^%s", items[4]); // NOLINT(runtime/printf)
} else {
- sprintf((char *)buf, "%s$", items[4]); // NOLINT(runtime/printf)
+ sprintf(buf, "%s$", items[4]); // NOLINT(runtime/printf)
}
- aff_entry->ae_prog = vim_regcomp((char *)buf, RE_MAGIC + RE_STRING + RE_STRICT);
+ aff_entry->ae_prog = vim_regcomp(buf, RE_MAGIC + RE_STRING + RE_STRICT);
if (aff_entry->ae_prog == NULL) {
smsg(_("Broken condition in %s line %d: %s"),
fname, lnum, items[4]);
@@ -2520,7 +2508,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
c_up = SPELL_TOUPPER(c);
if (c_up != c
&& (aff_entry->ae_cond == NULL
- || utf_ptr2char((char *)aff_entry->ae_cond) == c)) {
+ || utf_ptr2char(aff_entry->ae_cond) == c)) {
p = aff_entry->ae_add + strlen(aff_entry->ae_add);
MB_PTR_BACK(aff_entry->ae_add, p);
if (utf_ptr2char(p) == c_up) {
@@ -2532,13 +2520,13 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
// actual word, thus must check for the
// upper-case letter.
if (aff_entry->ae_cond != NULL) {
- char_u buf[MAXLINELEN];
- onecap_copy((char_u *)items[4], (char *)buf, true);
- aff_entry->ae_cond = (char_u *)getroom_save(spin, (char *)buf);
+ char buf[MAXLINELEN];
+ onecap_copy(items[4], buf, true);
+ aff_entry->ae_cond = getroom_save(spin, buf);
if (aff_entry->ae_cond != NULL) {
- sprintf((char *)buf, "^%s", aff_entry->ae_cond); // NOLINT(runtime/printf)
+ sprintf(buf, "^%s", aff_entry->ae_cond); // NOLINT(runtime/printf)
vim_regfree(aff_entry->ae_prog);
- aff_entry->ae_prog = vim_regcomp((char *)buf, RE_MAGIC + RE_STRING);
+ aff_entry->ae_prog = vim_regcomp(buf, RE_MAGIC + RE_STRING);
}
}
}
@@ -2553,7 +2541,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
// Find a previously used condition.
for (idx = spin->si_prefcond.ga_len - 1; idx >= 0; idx--) {
p = ((char **)spin->si_prefcond.ga_data)[idx];
- if (str_equal(p, (char *)aff_entry->ae_cond)) {
+ if (str_equal(p, aff_entry->ae_cond)) {
break;
}
}
@@ -2562,7 +2550,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
idx = spin->si_prefcond.ga_len;
pp = GA_APPEND_VIA_PTR(char_u *, &spin->si_prefcond);
*pp = (aff_entry->ae_cond == NULL) ?
- NULL : (char_u *)getroom_save(spin, (char *)aff_entry->ae_cond);
+ NULL : (char_u *)getroom_save(spin, aff_entry->ae_cond);
}
// Add the prefix to the prefix tree.
@@ -2608,7 +2596,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
} else if (is_aff_rule(items, itemcnt, "REP", 2)
|| is_aff_rule(items, itemcnt, "REPSAL", 2)) {
// Ignore REP/REPSAL count
- if (!isdigit(*items[1])) {
+ if (!isdigit((uint8_t)(*items[1]))) {
smsg(_("Expected REP(SAL) count in %s line %d"),
fname, lnum);
}
@@ -2643,7 +2631,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
if (!found_map) {
// First line contains the count.
found_map = true;
- if (!isdigit(*items[1])) {
+ if (!isdigit((uint8_t)(*items[1]))) {
smsg(_("Expected MAP count in %s line %d"),
fname, lnum);
}
@@ -2652,7 +2640,7 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
// Check that every character appears only once.
for (p = items[1]; *p != NUL;) {
- c = mb_ptr2char_adv((const char_u **)&p);
+ c = mb_ptr2char_adv((const char **)&p);
if ((!GA_EMPTY(&spin->si_map)
&& vim_strchr(spin->si_map.ga_data, c)
!= NULL)
@@ -2688,10 +2676,10 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
}
} else if (is_aff_rule(items, itemcnt, "SOFOFROM", 2)
&& sofofrom == NULL) {
- sofofrom = (char_u *)getroom_save(spin, items[1]);
+ sofofrom = getroom_save(spin, items[1]);
} else if (is_aff_rule(items, itemcnt, "SOFOTO", 2)
&& sofoto == NULL) {
- sofoto = (char_u *)getroom_save(spin, items[1]);
+ sofoto = getroom_save(spin, items[1]);
} else if (strcmp(items[0], "COMMON") == 0) {
int i;
@@ -2761,8 +2749,8 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
}
if (syllable != NULL) {
- aff_check_string(spin->si_syllable, (char *)syllable, "SYLLABLE");
- spin->si_syllable = (char *)syllable;
+ aff_check_string(spin->si_syllable, syllable, "SYLLABLE");
+ spin->si_syllable = syllable;
}
if (sofofrom != NULL || sofoto != NULL) {
@@ -2772,16 +2760,16 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char_u *fname)
} else if (!GA_EMPTY(&spin->si_sal)) {
smsg(_("Both SAL and SOFO lines in %s"), fname);
} else {
- aff_check_string(spin->si_sofofr, (char *)sofofrom, "SOFOFROM");
- aff_check_string(spin->si_sofoto, (char *)sofoto, "SOFOTO");
- spin->si_sofofr = (char *)sofofrom;
- spin->si_sofoto = (char *)sofoto;
+ aff_check_string(spin->si_sofofr, sofofrom, "SOFOFROM");
+ aff_check_string(spin->si_sofoto, sofoto, "SOFOTO");
+ spin->si_sofofr = sofofrom;
+ spin->si_sofoto = sofoto;
}
}
if (midword != NULL) {
- aff_check_string(spin->si_midword, (char *)midword, "MIDWORD");
- spin->si_midword = (char *)midword;
+ aff_check_string(spin->si_midword, midword, "MIDWORD");
+ spin->si_midword = midword;
}
xfree(pc);
@@ -2802,18 +2790,18 @@ static bool is_aff_rule(char **items, int itemcnt, char *rulename, int mincount)
// ae_flags to ae_comppermit and ae_compforbid.
static void aff_process_flags(afffile_T *affile, affentry_T *entry)
{
- char_u *p;
+ char *p;
char_u *prevp;
unsigned flag;
if (entry->ae_flags != NULL
&& (affile->af_compforbid != 0 || affile->af_comppermit != 0)) {
for (p = entry->ae_flags; *p != NUL;) {
- prevp = p;
+ prevp = (char_u *)p;
flag = get_affitem(affile->af_flagtype, &p);
if (flag == affile->af_comppermit || flag == affile->af_compforbid) {
STRMOVE(prevp, (char *)p);
- p = prevp;
+ p = (char *)prevp;
if (flag == affile->af_comppermit) {
entry->ae_comppermit = true;
} else {
@@ -2843,10 +2831,10 @@ static bool spell_info_item(char *s)
// Turn an affix flag name into a number, according to the FLAG type.
// returns zero for failure.
-static unsigned affitem2flag(int flagtype, char_u *item, char_u *fname, int lnum)
+static unsigned affitem2flag(int flagtype, char *item, char *fname, int lnum)
{
unsigned res;
- char_u *p = item;
+ char *p = item;
res = get_affitem(flagtype, &p);
if (res == 0) {
@@ -2869,7 +2857,7 @@ static unsigned affitem2flag(int flagtype, char_u *item, char_u *fname, int lnum
// Get one affix name from "*pp" and advance the pointer.
// Returns ZERO_FLAG for "0".
// Returns zero for an error, still advances the pointer then.
-static unsigned get_affitem(int flagtype, char_u **pp)
+static unsigned get_affitem(int flagtype, char **pp)
{
int res;
@@ -2878,18 +2866,18 @@ static unsigned get_affitem(int flagtype, char_u **pp)
(*pp)++; // always advance, avoid getting stuck
return 0;
}
- res = getdigits_int((char **)pp, true, 0);
+ res = getdigits_int(pp, true, 0);
if (res == 0) {
res = ZERO_FLAG;
}
} else {
- res = mb_ptr2char_adv((const char_u **)pp);
+ res = mb_ptr2char_adv((const char **)pp);
if (flagtype == AFT_LONG || (flagtype == AFT_CAPLONG
&& res >= 'A' && res <= 'Z')) {
if (**pp == NUL) {
return 0;
}
- res = mb_ptr2char_adv((const char_u **)pp) + (res << 16);
+ res = mb_ptr2char_adv((const char **)pp) + (res << 16);
}
}
return (unsigned)res;
@@ -2927,13 +2915,13 @@ static void process_compflags(spellinfo_T *spin, afffile_T *aff, char *compflags
tp = (char_u *)p + strlen(p);
for (p = compflags; *p != NUL;) {
- if (vim_strchr("/?*+[]", *p) != NULL) {
+ if (vim_strchr("/?*+[]", (uint8_t)(*p)) != NULL) {
// Copy non-flag characters directly.
*tp++ = (char_u)(*p++);
} else {
// First get the flag number, also checks validity.
prevp = p;
- flag = get_affitem(aff->af_flagtype, (char_u **)&p);
+ flag = get_affitem(aff->af_flagtype, &p);
if (flag != 0) {
// Find the flag in the hashtable. If it was used before, use
// the existing ID. Otherwise add a new entry.
@@ -2978,22 +2966,22 @@ static void check_renumber(spellinfo_T *spin)
}
// Returns true if flag "flag" appears in affix list "afflist".
-static bool flag_in_afflist(int flagtype, char_u *afflist, unsigned flag)
+static bool flag_in_afflist(int flagtype, char *afflist, unsigned flag)
{
char *p;
unsigned n;
switch (flagtype) {
case AFT_CHAR:
- return vim_strchr((char *)afflist, (int)flag) != NULL;
+ return vim_strchr(afflist, (int)flag) != NULL;
case AFT_CAPLONG:
case AFT_LONG:
- for (p = (char *)afflist; *p != NUL;) {
- n = (unsigned)mb_ptr2char_adv((const char_u **)&p);
+ for (p = afflist; *p != NUL;) {
+ n = (unsigned)mb_ptr2char_adv((const char **)&p);
if ((flagtype == AFT_LONG || (n >= 'A' && n <= 'Z'))
&& *p != NUL) {
- n = (unsigned)mb_ptr2char_adv((const char_u **)&p) + (n << 16);
+ n = (unsigned)mb_ptr2char_adv((const char **)&p) + (n << 16);
}
if (n == flag) {
return true;
@@ -3002,7 +2990,7 @@ static bool flag_in_afflist(int flagtype, char_u *afflist, unsigned flag)
break;
case AFT_NUM:
- for (p = (char *)afflist; *p != NUL;) {
+ for (p = afflist; *p != NUL;) {
int digits = getdigits_int(&p, true, 0);
assert(digits >= 0);
n = (unsigned int)digits;
@@ -3053,13 +3041,13 @@ static bool str_equal(char *s1, char *s2)
/// They are stored case-folded.
static void add_fromto(spellinfo_T *spin, garray_T *gap, char *from, char *to)
{
- char_u word[MAXWLEN];
+ char word[MAXWLEN];
fromto_T *ftp = GA_APPEND_VIA_PTR(fromto_T, gap);
- (void)spell_casefold(curwin, (char_u *)from, (int)strlen(from), word, MAXWLEN);
- ftp->ft_from = getroom_save(spin, (char *)word);
- (void)spell_casefold(curwin, (char_u *)to, (int)strlen(to), word, MAXWLEN);
- ftp->ft_to = getroom_save(spin, (char *)word);
+ (void)spell_casefold(curwin, from, (int)strlen(from), word, MAXWLEN);
+ ftp->ft_from = getroom_save(spin, word);
+ (void)spell_casefold(curwin, to, (int)strlen(to), word, MAXWLEN);
+ ftp->ft_to = getroom_save(spin, word);
}
/// Converts a boolean argument in a SAL line to true or false;
@@ -3103,7 +3091,7 @@ static void spell_free_aff(afffile_T *aff)
// Read dictionary file "fname".
// Returns OK or FAIL;
-static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
+static int spell_read_dic(spellinfo_T *spin, char *fname, afffile_T *affile)
{
hashtab_T ht;
char line[MAXLINELEN];
@@ -3128,7 +3116,7 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
Timestamp last_msg_time = 0;
// Open the file.
- fd = os_fopen((char *)fname, "r");
+ fd = os_fopen(fname, "r");
if (fd == NULL) {
semsg(_(e_notopen), fname);
return FAIL;
@@ -3229,7 +3217,7 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
break;
}
- hash = hash_hash((char_u *)dw);
+ hash = hash_hash(dw);
hi = hash_lookup(&ht, (const char *)dw, strlen(dw), hash);
if (!HASHITEM_EMPTY(hi)) {
if (p_verbose > 0) {
@@ -3241,7 +3229,7 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
}
duplicate++;
} else {
- hash_add_item(&ht, hi, (char_u *)dw, hash);
+ hash_add_item(&ht, hi, dw, hash);
}
flags = 0;
@@ -3250,43 +3238,43 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
need_affix = false;
if (afflist != NULL) {
// Extract flags from the affix list.
- flags |= get_affix_flags(affile, afflist);
+ flags |= get_affix_flags(affile, (char *)afflist);
if (affile->af_needaffix != 0
- && flag_in_afflist(affile->af_flagtype, afflist,
+ && flag_in_afflist(affile->af_flagtype, (char *)afflist,
affile->af_needaffix)) {
need_affix = true;
}
if (affile->af_pfxpostpone) {
// Need to store the list of prefix IDs with the word.
- pfxlen = get_pfxlist(affile, afflist, store_afflist);
+ pfxlen = get_pfxlist(affile, (char *)afflist, store_afflist);
}
if (spin->si_compflags != NULL) {
// Need to store the list of compound flags with the word.
// Concatenate them to the list of prefix IDs.
- get_compflags(affile, afflist, store_afflist + pfxlen);
+ get_compflags(affile, (char *)afflist, store_afflist + pfxlen);
}
}
// Add the word to the word tree(s).
if (store_word(spin, dw, flags, spin->si_region,
- store_afflist, need_affix) == FAIL) {
+ (char *)store_afflist, need_affix) == FAIL) {
retval = FAIL;
}
if (afflist != NULL) {
// Find all matching suffixes and add the resulting words.
// Additionally do matching prefixes that combine.
- if (store_aff_word(spin, dw, afflist, affile,
+ if (store_aff_word(spin, dw, (char *)afflist, affile,
&affile->af_suff, &affile->af_pref,
CONDIT_SUF, flags, (char *)store_afflist, pfxlen) == FAIL) {
retval = FAIL;
}
// Find all matching prefixes and add the resulting words.
- if (store_aff_word(spin, dw, afflist, affile,
+ if (store_aff_word(spin, dw, (char *)afflist, affile,
&affile->af_pref, NULL,
CONDIT_SUF, flags, (char *)store_afflist, pfxlen) == FAIL) {
retval = FAIL;
@@ -3311,7 +3299,7 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile)
// Check for affix flags in "afflist" that are turned into word flags.
// Return WF_ flags.
-static int get_affix_flags(afffile_T *affile, char_u *afflist)
+static int get_affix_flags(afffile_T *affile, char *afflist)
{
int flags = 0;
@@ -3350,9 +3338,9 @@ static int get_affix_flags(afffile_T *affile, char_u *afflist)
// Used for PFXPOSTPONE.
// Put the resulting flags in "store_afflist[MAXWLEN]" with a terminating NUL
// and return the number of affixes.
-static int get_pfxlist(afffile_T *affile, char_u *afflist, char_u *store_afflist)
+static int get_pfxlist(afffile_T *affile, char *afflist, char_u *store_afflist)
{
- char_u *p;
+ char *p;
char *prevp;
int cnt = 0;
int id;
@@ -3360,11 +3348,11 @@ static int get_pfxlist(afffile_T *affile, char_u *afflist, char_u *store_afflist
hashitem_T *hi;
for (p = afflist; *p != NUL;) {
- prevp = (char *)p;
+ prevp = p;
if (get_affitem(affile->af_flagtype, &p) != 0) {
// A flag is a postponed prefix flag if it appears in "af_pref"
// and its ID is not zero.
- xstrlcpy(key, prevp, (size_t)(p - (char_u *)prevp) + 1);
+ xstrlcpy(key, prevp, (size_t)(p - prevp) + 1);
hi = hash_find(&affile->af_pref, (char *)key);
if (!HASHITEM_EMPTY(hi)) {
id = HI2AH(hi)->ah_newID;
@@ -3385,19 +3373,19 @@ static int get_pfxlist(afffile_T *affile, char_u *afflist, char_u *store_afflist
// Get the list of compound IDs from the affix list "afflist" that are used
// for compound words.
// Puts the flags in "store_afflist[]".
-static void get_compflags(afffile_T *affile, char_u *afflist, char_u *store_afflist)
+static void get_compflags(afffile_T *affile, char *afflist, char_u *store_afflist)
{
- char_u *p;
+ char *p;
char *prevp;
int cnt = 0;
char key[AH_KEY_LEN];
hashitem_T *hi;
for (p = afflist; *p != NUL;) {
- prevp = (char *)p;
+ prevp = p;
if (get_affitem(affile->af_flagtype, &p) != 0) {
// A flag is a compound flag if it appears in "af_comp".
- xstrlcpy(key, prevp, (size_t)(p - (char_u *)prevp) + 1);
+ xstrlcpy(key, prevp, (size_t)(p - prevp) + 1);
hi = hash_find(&affile->af_comp, (char *)key);
if (!HASHITEM_EMPTY(hi)) {
store_afflist[cnt++] = (char_u)HI2CI(hi)->ci_newID;
@@ -3426,7 +3414,7 @@ static void get_compflags(afffile_T *affile, char_u *afflist, char_u *store_affl
/// @param pfxlen nr of flags in "pfxlist" for prefixes, rest is compound flags
///
/// @return FAIL when out of memory.
-static int store_aff_word(spellinfo_T *spin, char *word, char_u *afflist, afffile_T *affile,
+static int store_aff_word(spellinfo_T *spin, char *word, char *afflist, afffile_T *affile,
hashtab_T *ht, hashtab_T *xht, int condit, int flags, char *pfxlist,
int pfxlen)
{
@@ -3437,7 +3425,7 @@ static int store_aff_word(spellinfo_T *spin, char *word, char_u *afflist, afffil
char newword[MAXWLEN];
int retval = OK;
int i, j;
- char_u *p;
+ char *p;
int use_flags;
char *use_pfxlist;
int use_pfxlen;
@@ -3476,7 +3464,7 @@ static int store_aff_word(spellinfo_T *spin, char *word, char_u *afflist, afffil
&& (ae->ae_chop == NULL
|| strlen(ae->ae_chop) < wordlen)
&& (ae->ae_prog == NULL
- || vim_regexec_prog(&ae->ae_prog, false, (char_u *)word, (colnr_T)0))
+ || vim_regexec_prog(&ae->ae_prog, false, word, (colnr_T)0))
&& (((condit & CONDIT_CFIX) == 0)
== ((condit & CONDIT_AFF) == 0
|| ae->ae_flags == NULL
@@ -3490,7 +3478,7 @@ static int store_aff_word(spellinfo_T *spin, char *word, char_u *afflist, afffil
} else {
xstrlcpy(newword, ae->ae_add, MAXWLEN);
}
- p = (char_u *)word;
+ p = word;
if (ae->ae_chop != NULL) {
// Skip chop string.
i = mb_charlen(ae->ae_chop);
@@ -3504,7 +3492,7 @@ static int store_aff_word(spellinfo_T *spin, char *word, char_u *afflist, afffil
xstrlcpy(newword, word, MAXWLEN);
if (ae->ae_chop != NULL) {
// Remove chop string.
- p = (char_u *)newword + strlen(newword);
+ p = newword + strlen(newword);
i = mb_charlen(ae->ae_chop);
for (; i > 0; i--) {
MB_PTR_BACK(newword, p);
@@ -3525,16 +3513,18 @@ static int store_aff_word(spellinfo_T *spin, char *word, char_u *afflist, afffil
// Extract flags from the affix list.
use_flags |= get_affix_flags(affile, ae->ae_flags);
- if (affile->af_needaffix != 0 && flag_in_afflist(affile->af_flagtype, ae->ae_flags,
- affile->af_needaffix)) {
+ if (affile->af_needaffix != 0
+ && flag_in_afflist(affile->af_flagtype, ae->ae_flags,
+ affile->af_needaffix)) {
need_affix = true;
}
// When there is a CIRCUMFIX flag the other affix
// must also have it and we don't add the word
// with one affix.
- if (affile->af_circumfix != 0 && flag_in_afflist(affile->af_flagtype, ae->ae_flags,
- affile->af_circumfix)) {
+ if (affile->af_circumfix != 0
+ && flag_in_afflist(affile->af_flagtype, ae->ae_flags,
+ affile->af_circumfix)) {
use_condit |= CONDIT_CFIX;
if ((condit & CONDIT_CFIX) == 0) {
need_affix = true;
@@ -3545,8 +3535,7 @@ static int store_aff_word(spellinfo_T *spin, char *word, char_u *afflist, afffil
|| spin->si_compflags != NULL) {
if (affile->af_pfxpostpone) {
// Get prefix IDS from the affix list.
- use_pfxlen = get_pfxlist(affile,
- ae->ae_flags, store_afflist);
+ use_pfxlen = get_pfxlist(affile, ae->ae_flags, store_afflist);
} else {
use_pfxlen = 0;
}
@@ -3624,7 +3613,7 @@ static int store_aff_word(spellinfo_T *spin, char *word, char_u *afflist, afffil
// Store the modified word.
if (store_word(spin, newword, use_flags,
- spin->si_region, (char_u *)use_pfxlist,
+ spin->si_region, use_pfxlist,
need_affix) == FAIL) {
retval = FAIL;
}
@@ -3669,7 +3658,7 @@ static int store_aff_word(spellinfo_T *spin, char *word, char_u *afflist, afffil
}
// Read a file with a list of words.
-static int spell_read_wordfile(spellinfo_T *spin, char_u *fname)
+static int spell_read_wordfile(spellinfo_T *spin, char *fname)
{
FILE *fd;
long lnum = 0;
@@ -3685,7 +3674,7 @@ static int spell_read_wordfile(spellinfo_T *spin, char_u *fname)
int regionmask;
// Open the file.
- fd = os_fopen((char *)fname, "r");
+ fd = os_fopen(fname, "r");
if (fd == NULL) {
semsg(_(e_notopen), fname);
return FAIL;
@@ -3695,7 +3684,7 @@ static int spell_read_wordfile(spellinfo_T *spin, char_u *fname)
spell_message(spin, IObuff);
// Read all the lines in the file one by one.
- while (!vim_fgets((char *)rline, MAXLINELEN, fd) && !got_int) {
+ while (!vim_fgets(rline, MAXLINELEN, fd) && !got_int) {
line_breakcheck();
lnum++;
@@ -3866,7 +3855,7 @@ static void *getroom(spellinfo_T *spin, size_t len, bool align)
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 = xcalloc(1, offsetof(sblock_T, sb_data) + SBLOCKSIZE + 1);
bl->sb_next = spin->si_blocks;
spin->si_blocks = bl;
bl->sb_used = 0;
@@ -3935,11 +3924,11 @@ static bool valid_spell_word(const char *word, const char *end)
/// @param region supported region(s)
/// @param pfxlist list of prefix ids or null
/// @param need_affix only store word with affix id
-static int store_word(spellinfo_T *spin, char *word, int flags, int region, const char_u *pfxlist,
+static int store_word(spellinfo_T *spin, char *word, int flags, int region, const char *pfxlist,
bool need_affix)
{
int len = (int)strlen(word);
- int ct = captype((char_u *)word, (char_u *)word + len);
+ int ct = captype(word, word + len);
char_u foldword[MAXWLEN];
int res = OK;
@@ -3948,8 +3937,8 @@ static int store_word(spellinfo_T *spin, char *word, int flags, int region, cons
return FAIL;
}
- (void)spell_casefold(curwin, (char_u *)word, len, foldword, MAXWLEN);
- for (const char_u *p = pfxlist; res == OK; p++) {
+ (void)spell_casefold(curwin, word, len, (char *)foldword, MAXWLEN);
+ for (const char_u *p = (char_u *)pfxlist; res == OK; p++) {
if (!need_affix || (p != NULL && *p != NUL)) {
res = tree_add_word(spin, foldword, spin->si_foldroot, ct | flags,
region, p == NULL ? 0 : *p);
@@ -3961,7 +3950,7 @@ static int store_word(spellinfo_T *spin, char *word, int flags, int region, cons
spin->si_foldwcount++;
if (res == OK && (ct == WF_KEEPCAP || (flags & WF_KEEPCAP))) {
- for (const char_u *p = pfxlist; res == OK; p++) {
+ for (const char_u *p = (char_u *)pfxlist; res == OK; p++) {
if (!need_affix || (p != NULL && *p != NUL)) {
res = tree_add_word(spin, (char_u *)word, spin->si_keeproot, flags,
region, p == NULL ? 0 : *p);
@@ -4211,31 +4200,33 @@ static void wordtree_compress(spellinfo_T *spin, wordnode_T *root, const char *n
// Skip the root itself, it's not actually used. The first sibling is the
// start of the tree.
- if (root->wn_sibling != NULL) {
- hash_init(&ht);
- const long n = node_compress(spin, root->wn_sibling, &ht, &tot);
+ if (root->wn_sibling == NULL) {
+ return;
+ }
+
+ hash_init(&ht);
+ const long n = node_compress(spin, root->wn_sibling, &ht, &tot);
#ifndef SPELL_PRINTTREE
- if (spin->si_verbose || p_verbose > 2)
+ if (spin->si_verbose || p_verbose > 2)
#endif
- {
- if (tot > 1000000) {
- perc = (tot - n) / (tot / 100);
- } else if (tot == 0) {
- perc = 0;
- } else {
- perc = (tot - n) * 100 / tot;
- }
- vim_snprintf(IObuff, IOSIZE,
- _("Compressed %s of %ld nodes; %ld (%ld%%) remaining"),
- name, tot, tot - n, perc);
- spell_message(spin, IObuff);
+ {
+ if (tot > 1000000) {
+ perc = (tot - n) / (tot / 100);
+ } else if (tot == 0) {
+ perc = 0;
+ } else {
+ perc = (tot - n) * 100 / tot;
}
+ vim_snprintf(IObuff, IOSIZE,
+ _("Compressed %s of %ld nodes; %ld (%ld%%) remaining"),
+ name, tot, tot - n, perc);
+ spell_message(spin, IObuff);
+ }
#ifdef SPELL_PRINTTREE
- spell_print_tree(root->wn_sibling);
+ spell_print_tree(root->wn_sibling);
#endif
- hash_clear(&ht);
- }
+ hash_clear(&ht);
}
/// Compress a node, its siblings and its children, depth first.
@@ -4265,7 +4256,7 @@ static long node_compress(spellinfo_T *spin, wordnode_T *node, hashtab_T *ht, lo
compressed += node_compress(spin, child, ht, tot);
// Try to find an identical child.
- hash = hash_hash(child->wn_u1.hashkey);
+ hash = hash_hash((char *)child->wn_u1.hashkey);
hi = hash_lookup(ht, (const char *)child->wn_u1.hashkey,
strlen((char *)child->wn_u1.hashkey), hash);
if (!HASHITEM_EMPTY(hi)) {
@@ -4294,7 +4285,7 @@ static long node_compress(spellinfo_T *spin, wordnode_T *node, hashtab_T *ht, lo
} else {
// No other child has this hash value, add it to the
// hashtable.
- hash_add_item(ht, hi, child->wn_u1.hashkey, hash);
+ hash_add_item(ht, hi, (char *)child->wn_u1.hashkey, hash);
}
}
}
@@ -4901,10 +4892,12 @@ void ex_mkspell(exarg_T *eap)
}
// Expand all the remaining arguments (e.g., $VIMRUNTIME).
- if (get_arglist_exp(arg, &fcount, &fnames, false) == OK) {
- mkspell(fcount, fnames, ascii, eap->forceit, false);
- FreeWild(fcount, fnames);
+ if (get_arglist_exp(arg, &fcount, &fnames, false) != OK) {
+ return;
}
+
+ mkspell(fcount, fnames, ascii, eap->forceit, false);
+ FreeWild(fcount, fnames);
}
// Create the .sug file.
@@ -4974,7 +4967,7 @@ static void spell_make_sugfile(spellinfo_T *spin, char *wfname)
len = (int)strlen(fname);
fname[len - 2] = 'u';
fname[len - 1] = 'g';
- sug_write(spin, (char_u *)fname);
+ sug_write(spin, fname);
theend:
xfree(fname);
@@ -5008,7 +5001,7 @@ static int sug_filltree(spellinfo_T *spin, slang_T *slang)
// Go through the whole case-folded tree, soundfold each word and put it
// in the trie.
- byts = slang->sl_fbyts;
+ byts = (char_u *)slang->sl_fbyts;
idxs = slang->sl_fidxs;
arridx[0] = 0;
@@ -5199,10 +5192,10 @@ static int offset2bytes(int nr, char_u *buf)
}
// Write the .sug file in "fname".
-static void sug_write(spellinfo_T *spin, char_u *fname)
+static void sug_write(spellinfo_T *spin, char *fname)
{
// Create the file. Note that an existing file is silently overwritten!
- FILE *fd = os_fopen((char *)fname, "w");
+ FILE *fd = os_fopen(fname, "w");
if (fd == NULL) {
semsg(_(e_notopen), fname);
return;
@@ -5284,7 +5277,7 @@ theend:
/// @param added_word invoked through "zg"
static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool added_word)
{
- char_u *fname = NULL;
+ char *fname = NULL;
char **innames;
int incount;
afffile_T *(afile[MAXREGIONS]);
@@ -5301,9 +5294,9 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool
ga_init(&spin.si_rep, (int)sizeof(fromto_T), 20);
ga_init(&spin.si_repsal, (int)sizeof(fromto_T), 20);
ga_init(&spin.si_sal, (int)sizeof(fromto_T), 20);
- ga_init(&spin.si_map, (int)sizeof(char_u), 100);
- ga_init(&spin.si_comppat, (int)sizeof(char_u *), 20);
- ga_init(&spin.si_prefcond, (int)sizeof(char_u *), 50);
+ ga_init(&spin.si_map, (int)sizeof(char), 100);
+ ga_init(&spin.si_comppat, (int)sizeof(char *), 20);
+ ga_init(&spin.si_prefcond, (int)sizeof(char *), 50);
hash_init(&spin.si_commonwords);
spin.si_newcompID = 127; // start compound ID at first maximum
@@ -5325,14 +5318,14 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool
// For ":mkspell path/vim" output file is "path/vim.latin1.spl".
incount = 1;
vim_snprintf(wfname, MAXPATHL, SPL_FNAME_TMPL,
- fnames[0], spin.si_ascii ? (char_u *)"ascii" : spell_enc());
+ fnames[0], spin.si_ascii ? "ascii" : spell_enc());
} else if (len > 4 && strcmp(fnames[0] + len - 4, ".spl") == 0) {
// Name ends in ".spl", use as the file name.
xstrlcpy(wfname, fnames[0], MAXPATHL);
} else {
// Name should be language, make the file name from it.
vim_snprintf(wfname, MAXPATHL, SPL_FNAME_TMPL,
- fnames[0], spin.si_ascii ? (char_u *)"ascii" : spell_enc());
+ fnames[0], spin.si_ascii ? "ascii" : spell_enc());
}
// Check for .ascii.spl.
@@ -5404,8 +5397,8 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool
spin.si_conv.vc_type = CONV_NONE;
spin.si_region = 1 << i;
- vim_snprintf((char *)fname, MAXPATHL, "%s.aff", innames[i]);
- if (os_path_exists((char *)fname)) {
+ vim_snprintf(fname, MAXPATHL, "%s.aff", innames[i]);
+ if (os_path_exists(fname)) {
// Read the .aff file. Will init "spin->si_conv" based on the
// "SET" line.
afile[i] = spell_read_aff(&spin, fname);
@@ -5413,8 +5406,7 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool
error = true;
} else {
// Read the .dic file and store the words in the trees.
- vim_snprintf((char *)fname, MAXPATHL, "%s.dic",
- innames[i]);
+ vim_snprintf(fname, MAXPATHL, "%s.dic", innames[i]);
if (spell_read_dic(&spin, fname, afile[i]) == FAIL) {
error = true;
}
@@ -5422,7 +5414,7 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool
} else {
// No .aff file, try reading the file as a word list. Store
// the words in the trees.
- if (spell_read_wordfile(&spin, (char_u *)innames[i]) == FAIL) {
+ if (spell_read_wordfile(&spin, innames[i]) == FAIL) {
error = true;
}
}
@@ -5458,7 +5450,7 @@ static void mkspell(int fcount, char **fnames, bool ascii, bool over_write, bool
// If the file is loaded need to reload it.
if (!error) {
- spell_reload_one((char_u *)wfname, added_word);
+ spell_reload_one(wfname, added_word);
}
}
@@ -5534,11 +5526,11 @@ void spell_add_word(char *word, int len, SpellAddType what, int idx, bool undo)
buf_T *buf = NULL;
bool new_spf = false;
char *fname;
- char_u *fnamebuf = NULL;
+ char *fnamebuf = NULL;
char line[MAXWLEN * 2];
long fpos, fpos_next = 0;
int i;
- char_u *spf;
+ char *spf;
if (!valid_spell_word(word, word + len)) {
emsg(_(e_illegal_character_in_word));
@@ -5547,12 +5539,12 @@ void spell_add_word(char *word, int len, SpellAddType what, int idx, bool undo)
if (idx == 0) { // use internal wordlist
if (int_wordlist == NULL) {
- int_wordlist = (char_u *)vim_tempname();
+ int_wordlist = vim_tempname();
if (int_wordlist == NULL) {
return;
}
}
- fname = (char *)int_wordlist;
+ fname = int_wordlist;
} else {
// If 'spellfile' isn't set figure out a good default value.
if (*curwin->w_s->b_p_spf == NUL) {
@@ -5566,8 +5558,8 @@ void spell_add_word(char *word, int len, SpellAddType what, int idx, bool undo)
}
fnamebuf = xmalloc(MAXPATHL);
- for (spf = (char_u *)curwin->w_s->b_p_spf, i = 1; *spf != NUL; i++) {
- copy_option_part((char **)&spf, (char *)fnamebuf, MAXPATHL, ",");
+ for (spf = curwin->w_s->b_p_spf, i = 1; *spf != NUL; i++) {
+ copy_option_part(&spf, fnamebuf, MAXPATHL, ",");
if (i == idx) {
break;
}
@@ -5579,7 +5571,7 @@ void spell_add_word(char *word, int len, SpellAddType what, int idx, bool undo)
}
// Check that the user isn't editing the .add file somewhere.
- buf = buflist_findname_exp((char *)fnamebuf);
+ buf = buflist_findname_exp(fnamebuf);
if (buf != NULL && buf->b_ml.ml_mfp == NULL) {
buf = NULL;
}
@@ -5589,7 +5581,7 @@ void spell_add_word(char *word, int len, SpellAddType what, int idx, bool undo)
return;
}
- fname = (char *)fnamebuf;
+ fname = fnamebuf;
}
if (what == SPELL_ADD_BAD || undo) {
@@ -5690,82 +5682,84 @@ static void init_spellfile(void)
{
char *buf;
int l;
- char_u *fname;
- char_u *rtp;
- char_u *lend;
+ char *fname;
+ char *rtp;
+ char *lend;
bool aspath = false;
- char_u *lstart = (char_u *)curbuf->b_s.b_p_spl;
-
- if (*curwin->w_s->b_p_spl != NUL && !GA_EMPTY(&curwin->w_s->b_langp)) {
- buf = xmalloc(MAXPATHL);
-
- // Find the end of the language name. Exclude the region. If there
- // is a path separator remember the start of the tail.
- for (lend = (char_u *)curwin->w_s->b_p_spl; *lend != NUL
- && vim_strchr(",._", *lend) == NULL; lend++) {
- if (vim_ispathsep(*lend)) {
- aspath = true;
- lstart = lend + 1;
- }
+ char *lstart = curbuf->b_s.b_p_spl;
+
+ if (*curwin->w_s->b_p_spl == NUL || GA_EMPTY(&curwin->w_s->b_langp)) {
+ return;
+ }
+
+ buf = xmalloc(MAXPATHL);
+
+ // Find the end of the language name. Exclude the region. If there
+ // is a path separator remember the start of the tail.
+ for (lend = curwin->w_s->b_p_spl; *lend != NUL
+ && vim_strchr(",._", (uint8_t)(*lend)) == NULL; lend++) {
+ if (vim_ispathsep(*lend)) {
+ aspath = true;
+ lstart = lend + 1;
}
+ }
- // Loop over all entries in 'runtimepath'. Use the first one where we
- // are allowed to write.
- rtp = (char_u *)p_rtp;
- while (*rtp != NUL) {
+ // Loop over all entries in 'runtimepath'. Use the first one where we
+ // are allowed to write.
+ rtp = p_rtp;
+ while (*rtp != NUL) {
+ if (aspath) {
+ // Use directory of an entry with path, e.g., for
+ // "/dir/lg.utf-8.spl" use "/dir".
+ xstrlcpy(buf, curbuf->b_s.b_p_spl, (size_t)(lstart - curbuf->b_s.b_p_spl));
+ } else {
+ // Copy the path from 'runtimepath' to buf[].
+ copy_option_part(&rtp, buf, MAXPATHL, ",");
+ }
+ if (os_file_is_writable(buf) == 2) {
+ // Use the first language name from 'spelllang' and the
+ // encoding used in the first loaded .spl file.
if (aspath) {
- // Use directory of an entry with path, e.g., for
- // "/dir/lg.utf-8.spl" use "/dir".
- xstrlcpy(buf, curbuf->b_s.b_p_spl, (size_t)(lstart - (char_u *)curbuf->b_s.b_p_spl));
+ xstrlcpy(buf, curbuf->b_s.b_p_spl, (size_t)(lend - curbuf->b_s.b_p_spl + 1));
} else {
- // Copy the path from 'runtimepath' to buf[].
- copy_option_part((char **)&rtp, buf, MAXPATHL, ",");
- }
- if (os_file_is_writable(buf) == 2) {
- // Use the first language name from 'spelllang' and the
- // encoding used in the first loaded .spl file.
- if (aspath) {
- xstrlcpy(buf, curbuf->b_s.b_p_spl, (size_t)(lend - (char_u *)curbuf->b_s.b_p_spl + 1));
- } else {
- // Create the "spell" directory if it doesn't exist yet.
- l = (int)strlen(buf);
- vim_snprintf(buf + l, MAXPATHL - (size_t)l, "/spell");
- if (os_file_is_writable(buf) != 2) {
- os_mkdir(buf, 0755);
- }
-
- l = (int)strlen(buf);
- vim_snprintf(buf + l, MAXPATHL - (size_t)l,
- "/%.*s", (int)(lend - lstart), lstart);
+ // Create the "spell" directory if it doesn't exist yet.
+ l = (int)strlen(buf);
+ vim_snprintf(buf + l, MAXPATHL - (size_t)l, "/spell");
+ if (os_file_is_writable(buf) != 2) {
+ os_mkdir(buf, 0755);
}
+
l = (int)strlen(buf);
- fname = (char_u *)LANGP_ENTRY(curwin->w_s->b_langp, 0)
- ->lp_slang->sl_fname;
- vim_snprintf(buf + l, MAXPATHL - (size_t)l, ".%s.add",
- ((fname != NULL
- && strstr(path_tail((char *)fname), ".ascii.") != NULL)
- ? "ascii"
- : (const char *)spell_enc()));
- set_option_value_give_err("spellfile", 0L, (const char *)buf, OPT_LOCAL);
- break;
+ vim_snprintf(buf + l, MAXPATHL - (size_t)l,
+ "/%.*s", (int)(lend - lstart), lstart);
}
- aspath = false;
+ l = (int)strlen(buf);
+ fname = LANGP_ENTRY(curwin->w_s->b_langp, 0)
+ ->lp_slang->sl_fname;
+ vim_snprintf(buf + l, MAXPATHL - (size_t)l, ".%s.add",
+ ((fname != NULL
+ && strstr(path_tail(fname), ".ascii.") != NULL)
+ ? "ascii"
+ : (const char *)spell_enc()));
+ set_option_value_give_err("spellfile", 0L, buf, OPT_LOCAL);
+ break;
}
-
- xfree(buf);
+ aspath = false;
}
+
+ xfree(buf);
}
/// Set the spell character tables from strings in the .spl file.
///
/// @param cnt length of "flags"
-static void set_spell_charflags(const char_u *flags, int cnt, char_u *fol)
+static void set_spell_charflags(const char_u *flags, int cnt, char *fol)
{
// We build the new tables here first, so that we can compare with the
// previous one.
spelltab_T new_st;
int i;
- char_u *p = fol;
+ char *p = fol;
int c;
clear_spell_chartab(&new_st);
@@ -5777,7 +5771,7 @@ static void set_spell_charflags(const char_u *flags, int cnt, char_u *fol)
}
if (*p != NUL) {
- c = mb_ptr2char_adv((const char_u **)&p);
+ c = mb_ptr2char_adv((const char **)&p);
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] = (char_u)(i + 128);
@@ -5843,9 +5837,9 @@ static int write_spell_prefcond(FILE *fd, garray_T *gap, size_t *fwv)
}
// Use map string "map" for languages "lp".
-static void set_map_str(slang_T *lp, char_u *map)
+static void set_map_str(slang_T *lp, char *map)
{
- char_u *p;
+ char *p;
int headc = 0;
int c;
int i;
@@ -5866,7 +5860,7 @@ static void set_map_str(slang_T *lp, char_u *map)
// "aaa/bbb/ccc/". Fill sl_map_array[c] with the character before c and
// before the same slash. For characters above 255 sl_map_hash is used.
for (p = map; *p != NUL;) {
- c = mb_cptr2char_adv((const char_u **)&p);
+ c = mb_cptr2char_adv((const char **)&p);
if (c == '/') {
headc = 0;
} else {
@@ -5888,10 +5882,10 @@ static void set_map_str(slang_T *lp, char_u *map)
b[cl] = NUL;
utf_char2bytes(headc, b + cl + 1);
b[cl + 1 + headcl] = NUL;
- hash = hash_hash((char_u *)b);
+ hash = hash_hash(b);
hi = hash_lookup(&lp->sl_map_hash, (const char *)b, strlen(b), hash);
if (HASHITEM_EMPTY(hi)) {
- hash_add_item(&lp->sl_map_hash, hi, (char_u *)b, hash);
+ hash_add_item(&lp->sl_map_hash, hi, b, hash);
} else {
// This should have been checked when generating the .spl
// file.
diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c
index aef26ef288..54b6f552b5 100644
--- a/src/nvim/spellsuggest.c
+++ b/src/nvim/spellsuggest.c
@@ -276,26 +276,27 @@ static int score_wordcount_adj(slang_T *slang, int score, char_u *word, bool spl
int newscore;
hashitem_T *hi = hash_find(&slang->sl_wordcount, (char *)word);
- if (!HASHITEM_EMPTY(hi)) {
- wc = HI2WC(hi);
- if (wc->wc_count < SCORE_THRES2) {
- bonus = SCORE_COMMON1;
- } else if (wc->wc_count < SCORE_THRES3) {
- bonus = SCORE_COMMON2;
- } else {
- bonus = SCORE_COMMON3;
- }
- if (split) {
- newscore = score - bonus / 2;
- } else {
- newscore = score - bonus;
- }
- if (newscore < 0) {
- return 0;
- }
- return newscore;
+ if (HASHITEM_EMPTY(hi)) {
+ return score;
+ }
+
+ wc = HI2WC(hi);
+ if (wc->wc_count < SCORE_THRES2) {
+ bonus = SCORE_COMMON1;
+ } else if (wc->wc_count < SCORE_THRES3) {
+ bonus = SCORE_COMMON2;
+ } else {
+ bonus = SCORE_COMMON3;
}
- return score;
+ if (split) {
+ newscore = score - bonus / 2;
+ } else {
+ newscore = score - bonus;
+ }
+ if (newscore < 0) {
+ return 0;
+ }
+ return newscore;
}
/// Like captype() but for a KEEPCAP word add ONECAP if the word starts with a
@@ -304,42 +305,45 @@ static int score_wordcount_adj(slang_T *slang, int score, char_u *word, bool spl
static int badword_captype(char_u *word, char_u *end)
FUNC_ATTR_NONNULL_ALL
{
- int flags = captype(word, end);
+ int flags = captype((char *)word, (char *)end);
int c;
int l, u;
bool first;
char_u *p;
- if (flags & WF_KEEPCAP) {
- // Count the number of UPPER and lower case letters.
- l = u = 0;
- first = false;
- for (p = word; p < end; MB_PTR_ADV(p)) {
- c = utf_ptr2char((char *)p);
- if (SPELL_ISUPPER(c)) {
- u++;
- if (p == word) {
- first = true;
- }
- } else {
- l++;
+ if (!(flags & WF_KEEPCAP)) {
+ return flags;
+ }
+
+ // Count the number of UPPER and lower case letters.
+ l = u = 0;
+ first = false;
+ for (p = word; p < end; MB_PTR_ADV(p)) {
+ c = utf_ptr2char((char *)p);
+ if (SPELL_ISUPPER(c)) {
+ u++;
+ if (p == word) {
+ first = true;
}
+ } else {
+ l++;
}
+ }
- // If there are more UPPER than lower case letters suggest an
- // ALLCAP word. Otherwise, if the first letter is UPPER then
- // suggest ONECAP. Exception: "ALl" most likely should be "All",
- // require three upper case letters.
- if (u > l && u > 2) {
- flags |= WF_ALLCAP;
- } else if (first) {
- flags |= WF_ONECAP;
- }
+ // If there are more UPPER than lower case letters suggest an
+ // ALLCAP word. Otherwise, if the first letter is UPPER then
+ // suggest ONECAP. Exception: "ALl" most likely should be "All",
+ // require three upper case letters.
+ if (u > l && u > 2) {
+ flags |= WF_ALLCAP;
+ } else if (first) {
+ flags |= WF_ONECAP;
+ }
- if (u >= 2 && l >= 2) { // maCARONI maCAroni
- flags |= WF_MIXCAP;
- }
+ if (u >= 2 && l >= 2) { // maCARONI maCAroni
+ flags |= WF_MIXCAP;
}
+
return flags;
}
@@ -483,6 +487,11 @@ void spell_suggest(int count)
}
badlen++;
end_visual_mode();
+ // make sure we don't include the NUL at the end of the line
+ line = get_cursor_line_ptr();
+ if (badlen > (int)strlen(line) - (int)curwin->w_cursor.col) {
+ badlen = (int)strlen(line) - (int)curwin->w_cursor.col;
+ }
// Find the start of the badly spelled word.
} else if (spell_move_to(curwin, FORWARD, true, true, NULL) == 0
|| curwin->w_cursor.col > prev_cursor.col) {
@@ -492,15 +501,15 @@ void spell_suggest(int count)
line = get_cursor_line_ptr();
p = (char_u *)line + curwin->w_cursor.col;
// Backup to before start of word.
- while (p > (char_u *)line && spell_iswordp_nmw(p, curwin)) {
+ while (p > (char_u *)line && spell_iswordp_nmw((char *)p, curwin)) {
MB_PTR_BACK(line, p);
}
// Forward to start of word.
- while (*p != NUL && !spell_iswordp_nmw(p, curwin)) {
+ while (*p != NUL && !spell_iswordp_nmw((char *)p, curwin)) {
MB_PTR_ADV(p);
}
- if (!spell_iswordp_nmw(p, curwin)) { // No word found.
+ if (!spell_iswordp_nmw((char *)p, curwin)) { // No word found.
beep_flush();
return;
}
@@ -673,13 +682,13 @@ void spell_suggest(int count)
///
/// @param maxcount maximum nr of suggestions
/// @param need_cap 'spellcapcheck' matched
-void spell_suggest_list(garray_T *gap, char_u *word, int maxcount, bool need_cap, bool interactive)
+void spell_suggest_list(garray_T *gap, char *word, int maxcount, bool need_cap, bool interactive)
{
suginfo_T sug;
suggest_T *stp;
char_u *wcopy;
- spell_find_suggest(word, 0, &sug, maxcount, false, need_cap, interactive);
+ spell_find_suggest((char_u *)word, 0, &sug, maxcount, false, need_cap, interactive);
// Make room in "gap".
ga_init(gap, sizeof(char_u *), sug.su_ga.ga_len + 1);
@@ -733,7 +742,7 @@ static void spell_find_suggest(char_u *badptr, int badlen, suginfo_T *su, int ma
if (badlen != 0) {
su->su_badlen = badlen;
} else {
- size_t tmplen = spell_check(curwin, (char_u *)su->su_badptr, &attr, NULL, false);
+ size_t tmplen = spell_check(curwin, su->su_badptr, &attr, NULL, false);
assert(tmplen <= INT_MAX);
su->su_badlen = (int)tmplen;
}
@@ -744,7 +753,7 @@ static void spell_find_suggest(char_u *badptr, int badlen, suginfo_T *su, int ma
su->su_badlen = MAXWLEN - 1; // just in case
}
xstrlcpy((char *)su->su_badword, su->su_badptr, (size_t)su->su_badlen + 1);
- (void)spell_casefold(curwin, (char_u *)su->su_badptr, su->su_badlen, (char_u *)su->su_fbadword,
+ (void)spell_casefold(curwin, su->su_badptr, su->su_badlen, su->su_fbadword,
MAXWLEN);
// TODO(vim): make this work if the case-folded text is longer than the
@@ -783,7 +792,7 @@ static void spell_find_suggest(char_u *badptr, int badlen, suginfo_T *su, int ma
// for that.
c = utf_ptr2char(su->su_badptr);
if (!SPELL_ISUPPER(c) && attr == HLF_COUNT) {
- make_case_word((char_u *)su->su_badword, (char_u *)buf, WF_ONECAP);
+ make_case_word((char *)su->su_badword, buf, WF_ONECAP);
add_suggestion(su, &su->su_ga, (char *)buf, su->su_badlen, SCORE_ICASE,
0, true, su->su_sallang, false);
}
@@ -895,8 +904,8 @@ static void spell_suggest_file(suginfo_T *su, char_u *fname)
// If the suggestion doesn't have specific case duplicate the case
// of the bad word.
- if (captype(p, NULL) == 0) {
- make_case_word(p, cword, su->su_badflags);
+ if (captype((char *)p, NULL) == 0) {
+ make_case_word((char *)p, (char *)cword, su->su_badflags);
p = cword;
}
@@ -1016,7 +1025,7 @@ static void suggest_try_special(suginfo_T *su)
// use that for the goodword too: "The the" -> "The".
c = su->su_fbadword[len];
su->su_fbadword[len] = NUL;
- make_case_word((char_u *)su->su_fbadword, word, su->su_badflags);
+ make_case_word(su->su_fbadword, (char *)word, su->su_badflags);
su->su_fbadword[len] = c;
// Give a soundalike score of 0, compute the score as if deleting one
@@ -1085,7 +1094,7 @@ static void suggest_try_change(suginfo_T *su)
STRCPY(fword, su->su_fbadword);
n = (int)strlen(fword);
p = su->su_badptr + su->su_badlen;
- (void)spell_casefold(curwin, (char_u *)p, (int)strlen(p), (char_u *)fword + n, MAXWLEN - n);
+ (void)spell_casefold(curwin, p, (int)strlen(p), fword + n, MAXWLEN - n);
// Make sure the resulting text is not longer than the original text.
n = (int)strlen(su->su_badptr);
@@ -1193,7 +1202,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
if (soundfold) {
// Going through the soundfold tree.
- byts = fbyts = slang->sl_sbyts;
+ byts = fbyts = (char_u *)slang->sl_sbyts;
idxs = fidxs = slang->sl_sidxs;
pbyts = NULL;
pidxs = NULL;
@@ -1202,9 +1211,9 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
} else {
// When there are postponed prefixes we need to use these first. At
// the end of the prefix we continue in the case-fold tree.
- fbyts = slang->sl_fbyts;
+ fbyts = (char_u *)slang->sl_fbyts;
fidxs = slang->sl_fidxs;
- pbyts = slang->sl_pbyts;
+ pbyts = (char_u *)slang->sl_pbyts;
pidxs = slang->sl_pidxs;
if (pbyts != NULL) {
byts = pbyts;
@@ -1258,7 +1267,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
if (depth < MAXWLEN - 1 && (byts[arridx] == 0 || n == STATE_NOPREFIX)) {
// Set su->su_badflags to the caps type at this position.
// Use the caps type until here for the prefix itself.
- n = nofold_len((char_u *)fword, sp->ts_fidx, (char_u *)su->su_badptr);
+ n = nofold_len(fword, sp->ts_fidx, su->su_badptr);
flags = badword_captype((char_u *)su->su_badptr, (char_u *)su->su_badptr + n);
su->su_badflags = badword_captype((char_u *)su->su_badptr + n,
(char_u *)su->su_badptr + su->su_badlen);
@@ -1276,8 +1285,8 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
// Move the prefix to preword[] with the right case
// and make find_keepcap_word() works.
tword[sp->ts_twordlen] = NUL;
- make_case_word((char_u *)tword + sp->ts_splitoff,
- (char_u *)preword + sp->ts_prewordlen, flags);
+ make_case_word(tword + sp->ts_splitoff,
+ preword + sp->ts_prewordlen, flags);
sp->ts_prewordlen = (char_u)strlen(preword);
sp->ts_splitoff = sp->ts_twordlen;
}
@@ -1305,7 +1314,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
fword_ends = (fword[sp->ts_fidx] == NUL
|| (soundfold
? ascii_iswhite(fword[sp->ts_fidx])
- : !spell_iswordp((char_u *)fword + sp->ts_fidx, curwin)));
+ : !spell_iswordp(fword + sp->ts_fidx, curwin)));
tword[sp->ts_twordlen] = NUL;
if (sp->ts_prefixdepth <= PFD_NOTSPECIAL
@@ -1320,7 +1329,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
for (c = 0; c < len && pbyts[n + c] == 0; c++) {}
if (c > 0) {
c = valid_word_prefix(c, n, flags,
- (char_u *)tword + sp->ts_splitoff, slang, false);
+ tword + sp->ts_splitoff, slang, false);
if (c == 0) {
break;
}
@@ -1359,7 +1368,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
== sp->ts_twordlen - sp->ts_splitoff
&& strncmp(fword + sp->ts_splitfidx,
tword + sp->ts_splitoff,
- sp->ts_fidx - sp->ts_splitfidx) == 0) {
+ (size_t)(sp->ts_fidx - sp->ts_splitfidx)) == 0) {
preword[sp->ts_prewordlen] = NUL;
newscore = score_wordcount_adj(slang, sp->ts_score,
(char_u *)preword + sp->ts_prewordlen,
@@ -1441,11 +1450,11 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
// When appending a compound word after a word character don't
// use Onecap.
- if (p != NULL && spell_iswordp_nmw((char_u *)p, curwin)) {
+ if (p != NULL && spell_iswordp_nmw(p, curwin)) {
c &= ~WF_ONECAP;
}
- make_case_word((char_u *)tword + sp->ts_splitoff,
- (char_u *)preword + sp->ts_prewordlen, c);
+ make_case_word(tword + sp->ts_splitoff,
+ preword + sp->ts_prewordlen, c);
}
if (!soundfold) {
@@ -1477,7 +1486,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
}
if (!spell_valid_case(su->su_badflags,
- captype((char_u *)preword + sp->ts_prewordlen, NULL))) {
+ captype(preword + sp->ts_prewordlen, NULL))) {
newscore += SCORE_ICASE;
}
}
@@ -1508,10 +1517,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
// char, e.g., "thes," -> "these".
p = fword + sp->ts_fidx;
MB_PTR_BACK(fword, p);
- if (!spell_iswordp((char_u *)p, curwin) && *preword != NUL) {
+ if (!spell_iswordp(p, curwin) && *preword != NUL) {
p = preword + strlen(preword);
MB_PTR_BACK(preword, p);
- if (spell_iswordp((char_u *)p, curwin)) {
+ if (spell_iswordp(p, curwin)) {
newscore += SCORE_NONWORD;
}
}
@@ -1531,10 +1540,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
if (su->su_badflags & WF_MIXCAP) {
// We really don't know if the word should be
// upper or lower case, add both.
- c = captype((char_u *)preword, NULL);
+ c = captype(preword, NULL);
if (c == 0 || c == WF_ALLCAP) {
- make_case_word((char_u *)tword + sp->ts_splitoff,
- (char_u *)preword + sp->ts_prewordlen,
+ make_case_word(tword + sp->ts_splitoff,
+ preword + sp->ts_prewordlen,
c == 0 ? WF_ALLCAP : 0);
add_suggestion(su, &su->su_ga, (char *)preword,
@@ -1673,7 +1682,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
// non-word character with a space. Always skip a
// character when the word ends. But only when the
// good word can end.
- if (((!try_compound && !spell_iswordp_nmw((char_u *)fword
+ if (((!try_compound && !spell_iswordp_nmw(fword
+ sp->ts_fidx,
curwin))
|| fword_ends)
@@ -1705,7 +1714,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
// set su->su_badflags to the caps type at this
// position
- n = nofold_len((char_u *)fword, sp->ts_fidx, (char_u *)su->su_badptr);
+ n = nofold_len(fword, sp->ts_fidx, su->su_badptr);
su->su_badflags = badword_captype((char_u *)su->su_badptr + n,
(char_u *)su->su_badptr + su->su_badlen);
@@ -2029,7 +2038,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
// Don't swap if the first character is not a word character.
// SWAP3 etc. also don't make sense then.
- if (!soundfold && !spell_iswordp((char_u *)p, curwin)) {
+ if (!soundfold && !spell_iswordp(p, curwin)) {
PROF_STORE(sp->ts_state)
sp->ts_state = STATE_REP_INI;
break;
@@ -2039,7 +2048,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
c = utf_ptr2char(p);
if (p[n] == NUL) {
c2 = NUL;
- } else if (!soundfold && !spell_iswordp((char_u *)p + n, curwin)) {
+ } else if (!soundfold && !spell_iswordp(p + n, curwin)) {
c2 = c; // don't swap non-word char
} else {
c2 = utf_ptr2char(p + n);
@@ -2099,7 +2108,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
c = utf_ptr2char(p);
fl = utf_ptr2len(p + n);
c2 = utf_ptr2char(p + n);
- if (!soundfold && !spell_iswordp((char_u *)p + n + fl, curwin)) {
+ if (!soundfold && !spell_iswordp(p + n + fl, curwin)) {
c3 = c; // don't swap non-word char
} else {
c3 = utf_ptr2char(p + n + fl);
@@ -2150,7 +2159,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
utf_char2bytes(c2, p + tl);
p = p + tl;
- if (!soundfold && !spell_iswordp((char_u *)p, curwin)) {
+ if (!soundfold && !spell_iswordp(p, curwin)) {
// Middle char is not a word char, skip the rotate. First and
// third char were already checked at swap and swap3.
PROF_STORE(sp->ts_state)
@@ -2394,7 +2403,7 @@ static void find_keepcap_word(slang_T *slang, char *fword, char *kword)
int c;
idx_T lo, hi, m;
char_u *p;
- char_u *byts = slang->sl_kbyts; // array with bytes of the words
+ char_u *byts = (char_u *)slang->sl_kbyts; // array with bytes of the words
idx_T *idxs = slang->sl_kidxs; // array with indexes
if (byts == NULL) {
@@ -2404,7 +2413,7 @@ static void find_keepcap_word(slang_T *slang, char *fword, char *kword)
}
// Make an all-cap version of "fword".
- allcap_copy((char_u *)fword, (char_u *)uword);
+ allcap_copy(fword, uword);
// Each character needs to be tried both case-folded and upper-case.
// All this gets very complicated if we keep in mind that changing case
@@ -2661,7 +2670,7 @@ static int stp_sal_score(suggest_T *stp, suginfo_T *su, slang_T *slang, char_u *
pbad = badsound;
} else {
// soundfold the bad word with more characters following
- (void)spell_casefold(curwin, (char_u *)su->su_badptr, stp->st_orglen, fword, MAXWLEN);
+ (void)spell_casefold(curwin, su->su_badptr, stp->st_orglen, (char *)fword, MAXWLEN);
// When joining two words the sound often changes a lot. E.g., "t he"
// sounds like "t h" while "the" sounds like "@". Avoid that by
@@ -2814,15 +2823,15 @@ static void add_sound_suggest(suginfo_T *su, char *goodword, int score, langp_T
// times with different scores. Since the following is quite slow only do
// the words that have a better score than before. Use a hashtable to
// remember the words that have been done.
- hash = hash_hash((char_u *)goodword);
+ hash = hash_hash(goodword);
const size_t goodword_len = strlen(goodword);
hi = hash_lookup(&slang->sl_sounddone, (const char *)goodword, goodword_len,
hash);
if (HASHITEM_EMPTY(hi)) {
- sft = xmalloc(sizeof(sftword_T) + goodword_len);
+ sft = xmalloc(offsetof(sftword_T, sft_word) + goodword_len + 1);
sft->sft_score = (int16_t)score;
memcpy(sft->sft_word, goodword, goodword_len + 1);
- hash_add_item(&slang->sl_sounddone, hi, sft->sft_word, hash);
+ hash_add_item(&slang->sl_sounddone, hi, (char *)sft->sft_word, hash);
} else {
sft = HI2SFT(hi);
if (score >= sft->sft_score) {
@@ -2846,7 +2855,7 @@ static void add_sound_suggest(suginfo_T *su, char *goodword, int score, langp_T
// previous wordnr.
orgnr += bytes2offset(&nrline);
- byts = slang->sl_fbyts;
+ byts = (char_u *)slang->sl_fbyts;
idxs = slang->sl_fidxs;
// Lookup the word "orgnr" one of the two tries.
@@ -2904,7 +2913,7 @@ badword:
flags |= su->su_badflags;
if ((flags & WF_CAPMASK) != 0) {
// Need to fix case according to "flags".
- make_case_word(theword, cword, flags);
+ make_case_word((char *)theword, (char *)cword, flags);
p = cword;
} else {
p = theword;
@@ -2984,7 +2993,7 @@ static int soundfold_find(slang_T *slang, char_u *word)
idx_T *idxs;
int wordnr = 0;
- byts = slang->sl_sbyts;
+ byts = (char_u *)slang->sl_sbyts;
idxs = slang->sl_sidxs;
for (;;) {
@@ -3220,7 +3229,7 @@ static void check_suggestions(suginfo_T *su, garray_T *gap)
xstrlcpy(longword + len, su->su_badptr + stp[i].st_orglen,
(size_t)(MAXWLEN - len + 1));
attr = HLF_COUNT;
- (void)spell_check(curwin, (char_u *)longword, &attr, NULL, false);
+ (void)spell_check(curwin, longword, &attr, NULL, false);
if (attr != HLF_COUNT) {
// Remove this entry.
xfree(stp[i].st_word);
@@ -3239,13 +3248,14 @@ static void add_banned(suginfo_T *su, char *word)
hash_T hash;
hashitem_T *hi;
- hash = hash_hash((char_u *)word);
+ hash = hash_hash(word);
const size_t word_len = strlen(word);
hi = hash_lookup(&su->su_banned, word, word_len, hash);
- if (HASHITEM_EMPTY(hi)) {
- s = xmemdupz(word, word_len);
- hash_add_item(&su->su_banned, hi, s, hash);
+ if (!HASHITEM_EMPTY(hi)) { // already present
+ return;
}
+ s = xmemdupz(word, word_len);
+ hash_add_item(&su->su_banned, hi, (char *)s, hash);
}
/// Recompute the score for all suggestions if sound-folding is possible. This
@@ -3312,21 +3322,23 @@ static int sug_compare(const void *s1, const void *s2)
static int cleanup_suggestions(garray_T *gap, int maxscore, int keep)
FUNC_ATTR_NONNULL_ALL
{
- if (gap->ga_len > 0) {
- // Sort the list.
- qsort(gap->ga_data, (size_t)gap->ga_len, sizeof(suggest_T), sug_compare);
+ if (gap->ga_len <= 0) {
+ return maxscore;
+ }
- // Truncate the list to the number of suggestions that will be displayed.
- if (gap->ga_len > keep) {
- suggest_T *const stp = &SUG(*gap, 0);
+ // Sort the list.
+ qsort(gap->ga_data, (size_t)gap->ga_len, sizeof(suggest_T), sug_compare);
- for (int i = keep; i < gap->ga_len; i++) {
- xfree(stp[i].st_word);
- }
- gap->ga_len = keep;
- if (keep >= 1) {
- return stp[keep - 1].st_score;
- }
+ // Truncate the list to the number of suggestions that will be displayed.
+ if (gap->ga_len > keep) {
+ suggest_T *const stp = &SUG(*gap, 0);
+
+ for (int i = keep; i < gap->ga_len; i++) {
+ xfree(stp[i].st_word);
+ }
+ gap->ga_len = keep;
+ if (keep >= 1) {
+ return stp[keep - 1].st_score;
}
}
return maxscore;
@@ -3580,12 +3592,12 @@ static int spell_edit_score(slang_T *slang, const char_u *badword, const char_u
// Get the characters from the multi-byte strings and put them in an
// int array for easy access.
badlen = 0;
- for (const char_u *p = badword; *p != NUL;) {
+ for (const char *p = (char *)badword; *p != NUL;) {
wbadword[badlen++] = mb_cptr2char_adv(&p);
}
wbadword[badlen++] = 0;
goodlen = 0;
- for (const char_u *p = goodword; *p != NUL;) {
+ for (const char *p = (char *)goodword; *p != NUL;) {
wgoodword[goodlen++] = mb_cptr2char_adv(&p);
}
wgoodword[goodlen++] = 0;
@@ -3686,12 +3698,12 @@ static int spell_edit_score_limit_w(slang_T *slang, const char_u *badword, const
// Get the characters from the multi-byte strings and put them in an
// int array for easy access.
bi = 0;
- for (const char_u *p = badword; *p != NUL;) {
+ for (const char *p = (char *)badword; *p != NUL;) {
wbadword[bi++] = mb_cptr2char_adv(&p);
}
wbadword[bi++] = 0;
gi = 0;
- for (const char_u *p = goodword; *p != NUL;) {
+ for (const char *p = (char *)goodword; *p != NUL;) {
wgoodword[gi++] = mb_cptr2char_adv(&p);
}
wgoodword[gi++] = 0;
diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c
index db3e3f91bf..6ad1f31143 100644
--- a/src/nvim/statusline.c
+++ b/src/nvim/statusline.c
@@ -31,12 +31,14 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/move.h"
+#include "nvim/normal.h"
#include "nvim/option.h"
#include "nvim/optionstr.h"
#include "nvim/os/os.h"
#include "nvim/path.h"
#include "nvim/pos.h"
#include "nvim/screen.h"
+#include "nvim/sign_defs.h"
#include "nvim/statusline.h"
#include "nvim/strings.h"
#include "nvim/types.h"
@@ -229,8 +231,12 @@ void stl_fill_click_defs(StlClickDefinition *click_defs, StlClickRecord *click_r
};
for (int i = 0; click_recs[i].start != NULL; i++) {
len += vim_strnsize(buf, (int)(click_recs[i].start - buf));
- while (col < len) {
- click_defs[col++] = cur_click_def;
+ if (col < len) {
+ while (col < len) {
+ click_defs[col++] = cur_click_def;
+ }
+ } else {
+ xfree(cur_click_def.func);
}
buf = (char *)click_recs[i].start;
cur_click_def = click_recs[i].def;
@@ -240,8 +246,12 @@ void stl_fill_click_defs(StlClickDefinition *click_defs, StlClickRecord *click_r
cur_click_def.type = kStlClickDisabled;
}
}
- while (col < width) {
- click_defs[col++] = cur_click_def;
+ if (col < width) {
+ while (col < width) {
+ click_defs[col++] = cur_click_def;
+ }
+ } else {
+ xfree(cur_click_def.func);
}
}
@@ -713,7 +723,7 @@ void draw_tabline(void)
int len;
int attr_nosel = HL_ATTR(HLF_TP);
int attr_fill = HL_ATTR(HLF_TPF);
- char_u *p;
+ char *p;
int room;
int use_sep_chars = (t_colors < 8);
@@ -731,6 +741,10 @@ void draw_tabline(void)
return;
}
+ // Clear tab_page_click_defs: Clicking outside of tabs has no effect.
+ assert(tab_page_click_defs_size >= (size_t)Columns);
+ stl_clear_click_defs(tab_page_click_defs, tab_page_click_defs_size);
+
// Use the 'tabline' option if it's set.
if (*p_tal != NUL) {
win_redr_custom(NULL, false, false);
@@ -809,16 +823,16 @@ void draw_tabline(void)
get_trans_bufname(cwp->w_buffer);
shorten_dir(NameBuff);
len = vim_strsize(NameBuff);
- p = (char_u *)NameBuff;
+ p = NameBuff;
while (len > room) {
- len -= ptr2cells((char *)p);
+ len -= ptr2cells(p);
MB_PTR_ADV(p);
}
if (len > Columns - col - 1) {
len = Columns - col - 1;
}
- grid_puts_len(&default_grid, (char *)p, (int)strlen((char *)p), 0, col, attr);
+ grid_puts_len(&default_grid, p, (int)strlen(p), 0, col, attr);
col += len;
}
grid_putchar(&default_grid, ' ', 0, col++, attr);
@@ -868,29 +882,30 @@ void draw_tabline(void)
redraw_tabline = false;
}
-/// Build the 'statuscolumn' string for line "lnum". If "setnum" is true,
-/// update the "lnum" and "relnum" vim-variables for a new line.
+/// Build the 'statuscolumn' string for line "lnum". When "relnum" == -1,
+/// the v:lnum and v:relnum variables don't have to be updated.
///
/// @param hlrec HL attributes (can be NULL)
/// @param stcp Status column attributes (can be NULL)
/// @return The width of the built status column string for line "lnum"
-int build_statuscol_str(win_T *wp, bool setnum, bool wrap, linenr_T lnum, long relnum, int maxwidth,
- int fillchar, char *buf, stl_hlrec_t **hlrec, statuscol_T *stcp)
+int build_statuscol_str(win_T *wp, linenr_T lnum, long relnum, int maxwidth, int fillchar,
+ char *buf, stl_hlrec_t **hlrec, statuscol_T *stcp)
{
- if (setnum) {
+ bool fillclick = relnum >= 0 && lnum == wp->w_topline;
+
+ if (relnum >= 0) {
set_vim_var_nr(VV_LNUM, lnum);
set_vim_var_nr(VV_RELNUM, relnum);
}
- set_vim_var_bool(VV_WRAP, wrap);
StlClickRecord *clickrec;
char *stc = xstrdup(wp->w_p_stc);
- int width = build_stl_str_hl(wp, buf, MAXPATHL, stc, "statuscolumn", OPT_LOCAL,
- fillchar, maxwidth, hlrec, &clickrec, stcp);
+ int width = build_stl_str_hl(wp, buf, MAXPATHL, stc, "statuscolumn", OPT_LOCAL, fillchar,
+ maxwidth, hlrec, fillclick ? &clickrec : NULL, stcp);
xfree(stc);
- // Allocate and fill click def array if width has changed
- if (wp->w_status_click_defs_size != (size_t)width) {
+ // Only update click definitions once per window per redraw
+ if (fillclick) {
stl_clear_click_defs(wp->w_statuscol_click_defs, wp->w_statuscol_click_defs_size);
wp->w_statuscol_click_defs = stl_alloc_click_defs(wp->w_statuscol_click_defs, width,
&wp->w_statuscol_click_defs_size);
@@ -1322,7 +1337,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
}
stl_items[curitem].type = ClickFunc;
stl_items[curitem].start = out_p;
- stl_items[curitem].cmd = xmemdupz(t, (size_t)(fmt_p - t));
+ stl_items[curitem].cmd = tabtab ? xmemdupz(t, (size_t)(fmt_p - t)) : NULL;
stl_items[curitem].minwid = minwid;
fmt_p++;
curitem++;
@@ -1363,7 +1378,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
// An invalid item was specified.
// Continue processing on the next character of the format string.
- if (vim_strchr(STL_ALL, *fmt_p) == NULL) {
+ if (vim_strchr(STL_ALL, (uint8_t)(*fmt_p)) == NULL) {
fmt_p++;
continue;
}
@@ -1504,13 +1519,12 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
case STL_LINE:
// Overload %l with v:lnum for 'statuscolumn'
if (opt_name != NULL && strcmp(opt_name, "statuscolumn") == 0) {
- if (wp->w_p_nu) {
+ if (wp->w_p_nu && !get_vim_var_nr(VV_VIRTNUM)) {
num = get_vim_var_nr(VV_LNUM);
}
} else {
num = (wp->w_buffer->b_ml.ml_flags & ML_EMPTY) ? 0L : (long)(wp->w_cursor.lnum);
}
-
break;
case STL_NUMLINES:
@@ -1610,7 +1624,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
case STL_ROFLAG_ALT:
// Overload %r with v:relnum for 'statuscolumn'
if (opt_name != NULL && strcmp(opt_name, "statuscolumn") == 0) {
- if (wp->w_p_rnu) {
+ if (wp->w_p_rnu && !get_vim_var_nr(VV_VIRTNUM)) {
num = get_vim_var_nr(VV_RELNUM);
}
} else {
@@ -1678,7 +1692,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
vim_snprintf(buf_tmp, sizeof(buf_tmp), ",%s", wp->w_buffer->b_p_ft);
// Uppercase the file extension
for (char *t = buf_tmp; *t != 0; t++) {
- *t = (char)TOUPPER_LOC(*t);
+ *t = (char)TOUPPER_LOC((uint8_t)(*t));
}
str = buf_tmp;
}
@@ -1978,6 +1992,11 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
// the truncation point
for (int i = 0; i < itemcnt; i++) {
if (stl_items[i].start > trunc_p) {
+ for (int j = i; j < itemcnt; j++) {
+ if (stl_items[j].type == ClickFunc) {
+ XFREE_CLEAR(stl_items[j].cmd);
+ }
+ }
itemcnt = i;
break;
}
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index f0f9fbf51b..34b3c38103 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -167,7 +167,7 @@ char *vim_strsave_shellescape(const char *string, bool do_special, bool do_newli
// First count the number of extra bytes required.
size_t length = strlen(string) + 3; // two quotes and a trailing NUL
- for (const char_u *p = (char_u *)string; *p != NUL; MB_PTR_ADV(p)) {
+ for (const char *p = string; *p != NUL; MB_PTR_ADV(p)) {
#ifdef MSWIN
if (!p_ssl) {
if (*p == '"') {
@@ -185,7 +185,7 @@ char *vim_strsave_shellescape(const char *string, bool do_special, bool do_newli
length++; // insert backslash
}
}
- if (do_special && find_cmdline_var((char *)p, &l) >= 0) {
+ if (do_special && find_cmdline_var(p, &l) >= 0) {
length++; // insert backslash
p += l - 1;
}
@@ -270,7 +270,7 @@ char *vim_strsave_up(const char *string)
char *p1;
p1 = xstrdup(string);
- vim_strup((char_u *)p1);
+ vim_strup(p1);
return p1;
}
@@ -280,17 +280,17 @@ char *vim_strnsave_up(const char *string, size_t len)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
{
char *p1 = xstrnsave(string, len);
- vim_strup((char_u *)p1);
+ vim_strup(p1);
return p1;
}
// ASCII lower-to-upper case translation, language independent.
-void vim_strup(char_u *p)
+void vim_strup(char *p)
FUNC_ATTR_NONNULL_ALL
{
- char_u c;
- while ((c = *p) != NUL) {
- *p++ = (char_u)(c < 'a' || c > 'z' ? c : c - 0x20);
+ uint8_t c;
+ while ((c = (uint8_t)(*p)) != NUL) {
+ *p++ = (char)(uint8_t)(c < 'a' || c > 'z' ? c : c - 0x20);
}
}
@@ -313,7 +313,7 @@ char *strcase_save(const char *const orig, bool upper)
int l = utf_ptr2len(p);
if (c == 0) {
// overlong sequence, use only the first byte
- c = (char_u)(*p);
+ c = (uint8_t)(*p);
l = 1;
}
int uc = upper ? mb_toupper(c) : mb_tolower(c);
@@ -372,7 +372,7 @@ int vim_stricmp(const char *s1, const char *s2)
int i;
for (;;) {
- i = (int)TOLOWER_LOC(*s1) - (int)TOLOWER_LOC(*s2);
+ i = (int)TOLOWER_LOC((uint8_t)(*s1)) - (int)TOLOWER_LOC((uint8_t)(*s2));
if (i != 0) {
return i; // this character different
}
@@ -396,7 +396,7 @@ int vim_strnicmp(const char *s1, const char *s2, size_t len)
int i;
while (len > 0) {
- i = (int)TOLOWER_LOC(*s1) - (int)TOLOWER_LOC(*s2);
+ i = (int)TOLOWER_LOC((uint8_t)(*s1)) - (int)TOLOWER_LOC((uint8_t)(*s2));
if (i != 0) {
return i; // this character different
}
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 721cc7707a..49b63ad324 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -92,7 +92,7 @@ typedef struct syn_pattern {
} synpat_T;
typedef struct syn_cluster_S {
- char_u *scl_name; // syntax cluster name
+ char *scl_name; // syntax cluster name
char *scl_name_u; // uppercase of scl_name
int16_t *scl_list; // IDs in this syntax cluster
} syn_cluster_T;
@@ -721,10 +721,12 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
static void save_chartab(char *chartab)
{
- if (syn_block->b_syn_isk != empty_option) {
- memmove(chartab, syn_buf->b_chartab, (size_t)32);
- memmove(syn_buf->b_chartab, syn_win->w_s->b_syn_chartab, (size_t)32);
+ if (syn_block->b_syn_isk == empty_option) {
+ return;
}
+
+ memmove(chartab, syn_buf->b_chartab, (size_t)32);
+ memmove(syn_buf->b_chartab, syn_win->w_s->b_syn_chartab, (size_t)32);
}
static void restore_chartab(char *chartab)
@@ -737,22 +739,23 @@ static void restore_chartab(char *chartab)
/// Return true if the line-continuation pattern matches in line "lnum".
static int syn_match_linecont(linenr_T lnum)
{
- if (syn_block->b_syn_linecont_prog != NULL) {
- regmmatch_T regmatch;
- // chartab array for syn iskeyword
- char buf_chartab[32];
- save_chartab(buf_chartab);
+ if (syn_block->b_syn_linecont_prog == NULL) {
+ return false;
+ }
- regmatch.rmm_ic = syn_block->b_syn_linecont_ic;
- regmatch.regprog = syn_block->b_syn_linecont_prog;
- int r = syn_regexec(&regmatch, lnum, (colnr_T)0,
- IF_SYN_TIME(&syn_block->b_syn_linecont_time));
- syn_block->b_syn_linecont_prog = regmatch.regprog;
+ regmmatch_T regmatch;
+ // chartab array for syn iskeyword
+ char buf_chartab[32];
+ save_chartab(buf_chartab);
- restore_chartab(buf_chartab);
- return r;
- }
- return false;
+ regmatch.rmm_ic = syn_block->b_syn_linecont_ic;
+ regmatch.regprog = syn_block->b_syn_linecont_prog;
+ int r = syn_regexec(&regmatch, lnum, (colnr_T)0,
+ IF_SYN_TIME(&syn_block->b_syn_linecont_time));
+ syn_block->b_syn_linecont_prog = regmatch.regprog;
+
+ restore_chartab(buf_chartab);
+ return r;
}
// Prepare the current state for the start of a line.
@@ -873,14 +876,16 @@ static void syn_stack_free_block(synblock_T *block)
{
synstate_T *p;
- if (block->b_sst_array != NULL) {
- for (p = block->b_sst_first; p != NULL; p = p->sst_next) {
- clear_syn_state(p);
- }
- XFREE_CLEAR(block->b_sst_array);
- block->b_sst_first = NULL;
- block->b_sst_len = 0;
+ if (block->b_sst_array == NULL) {
+ return;
+ }
+
+ for (p = block->b_sst_first; p != NULL; p = p->sst_next) {
+ clear_syn_state(p);
}
+ XFREE_CLEAR(block->b_sst_array);
+ block->b_sst_first = NULL;
+ block->b_sst_len = 0;
}
// Free b_sst_array[] for buffer "buf".
// Used when syntax items changed to force resyncing everywhere.
@@ -1490,8 +1495,8 @@ int get_syntax_attr(const colnr_T col, bool *const can_spell, const bool keep_st
static int syn_current_attr(const bool syncing, const bool displaying, bool *const can_spell,
const bool keep_state)
{
- lpos_T endpos; // was: char_u *endp;
- lpos_T hl_startpos; // was: int hl_startcol;
+ lpos_T endpos;
+ lpos_T hl_startpos;
lpos_T hl_endpos;
lpos_T eos_pos; // end-of-start match (start region)
lpos_T eoe_pos; // end-of-end pattern
@@ -3416,8 +3421,8 @@ static void syn_list_one(const int id, const bool syncing, const bool link_only)
}
msg_putchar(' ');
if (spp->sp_sync_idx >= 0) {
- msg_outtrans((char *)highlight_group_name(SYN_ITEMS(curwin->w_s)
- [spp->sp_sync_idx].sp_syn.id - 1));
+ msg_outtrans(highlight_group_name(SYN_ITEMS(curwin->w_s)
+ [spp->sp_sync_idx].sp_syn.id - 1));
} else {
msg_puts("NONE");
}
@@ -3430,7 +3435,7 @@ static void syn_list_one(const int id, const bool syncing, const bool link_only)
(void)syn_list_header(did_header, 0, id, true);
msg_puts_attr("links to", attr);
msg_putchar(' ');
- msg_outtrans((char *)highlight_group_name(highlight_link_id(id - 1) - 1));
+ msg_outtrans(highlight_group_name(highlight_link_id(id - 1) - 1));
}
}
@@ -3453,7 +3458,7 @@ static void syn_list_cluster(int id)
// slight hack: roughly duplicate the guts of syn_list_header()
msg_putchar('\n');
- msg_outtrans((char *)SYN_CLSTR(curwin->w_s)[id].scl_name);
+ msg_outtrans(SYN_CLSTR(curwin->w_s)[id].scl_name);
if (msg_col >= endcol) { // output at least one space
endcol = msg_col + 1;
@@ -3490,9 +3495,9 @@ static void put_id_list(const char *const name, const int16_t *const list, const
int scl_id = *p - SYNID_CLUSTER;
msg_putchar('@');
- msg_outtrans((char *)SYN_CLSTR(curwin->w_s)[scl_id].scl_name);
+ msg_outtrans(SYN_CLSTR(curwin->w_s)[scl_id].scl_name);
} else {
- msg_outtrans((char *)highlight_group_name(*p - 1));
+ msg_outtrans(highlight_group_name(*p - 1));
}
if (p[1]) {
msg_putchar(',');
@@ -3514,7 +3519,7 @@ static void put_pattern(const char *const s, const int c, const synpat_T *const
if (last_matchgroup == 0) {
msg_outtrans("NONE");
} else {
- msg_outtrans((char *)highlight_group_name(last_matchgroup - 1));
+ msg_outtrans(highlight_group_name(last_matchgroup - 1));
}
msg_putchar(' ');
}
@@ -3524,7 +3529,7 @@ static void put_pattern(const char *const s, const int c, const synpat_T *const
msg_putchar(c);
// output the pattern, in between a char that is not in the pattern
- for (i = 0; vim_strchr(spp->sp_pattern, sepchars[i]) != NULL;) {
+ for (i = 0; vim_strchr(spp->sp_pattern, (uint8_t)sepchars[i]) != NULL;) {
if (sepchars[++i] == NUL) {
i = 0; // no good char found, just use the first one
break;
@@ -3731,7 +3736,7 @@ static void add_keyword(char *const name, const int id, const int flags,
sizeof(name_folded))
: name;
- keyentry_T *const kp = xmalloc(sizeof(keyentry_T) + strlen(name_ic));
+ keyentry_T *const kp = xmalloc(offsetof(keyentry_T, keyword) + strlen(name_ic) + 1);
STRCPY(kp->keyword, name_ic);
kp->k_syn.id = (int16_t)id;
kp->k_syn.inc_tag = current_syn_inc_tag;
@@ -3743,7 +3748,7 @@ static void add_keyword(char *const name, const int id, const int flags,
}
kp->next_list = copy_id_list(next_list);
- const hash_T hash = hash_hash((char_u *)kp->keyword);
+ const hash_T hash = hash_hash(kp->keyword);
hashtab_T *const ht = (curwin->w_s->b_syn_ic)
? &curwin->w_s->b_keywtab_ic
: &curwin->w_s->b_keywtab;
@@ -3757,7 +3762,7 @@ static void add_keyword(char *const name, const int id, const int flags,
if (HASHITEM_EMPTY(hi)) {
// new keyword, add to hashtable
kp->ke_next = NULL;
- hash_add_item(ht, hi, (char_u *)kp->keyword, hash);
+ hash_add_item(ht, hi, kp->keyword, hash);
} else {
// keyword already exists, prepend to list
kp->ke_next = HI2KE(hi);
@@ -4000,7 +4005,7 @@ static void syn_cmd_include(exarg_T *eap, int syncing)
// filename to include.
eap->argt |= (EX_XFILE | EX_NOSPC);
separate_nextcmd(eap);
- if (*eap->arg == '<' || *eap->arg == '$' || path_is_absolute((char_u *)eap->arg)) {
+ if (*eap->arg == '<' || *eap->arg == '$' || path_is_absolute(eap->arg)) {
// For an absolute path, "$VIM/..." or "<sfile>.." we ":source" the
// file. Need to expand the file name first. In other cases
// ":runtime!" is used.
@@ -4634,7 +4639,7 @@ static int syn_add_cluster(char *name)
syn_cluster_T *scp = GA_APPEND_VIA_PTR(syn_cluster_T,
&curwin->w_s->b_syn_clusters);
CLEAR_POINTER(scp);
- scp->scl_name = (char_u *)name;
+ scp->scl_name = name;
scp->scl_name_u = vim_strsave_up(name);
scp->scl_list = NULL;
@@ -5042,7 +5047,7 @@ static int get_id_list(char **const arg, const int keylen, int16_t **const list,
regmatch.rm_ic = true;
id = 0;
for (int i = highlight_num_groups(); --i >= 0;) {
- if (vim_regexec(&regmatch, (char *)highlight_group_name(i), (colnr_T)0)) {
+ if (vim_regexec(&regmatch, highlight_group_name(i), (colnr_T)0)) {
if (round == 2) {
// Got more items than expected; can happen
// when adding items that match:
@@ -5369,34 +5374,39 @@ void set_context_in_syntax_cmd(expand_T *xp, const char *arg)
include_link = 0;
include_default = 0;
+ if (*arg == NUL) {
+ return;
+ }
+
// (part of) subcommand already typed
- if (*arg != NUL) {
- const char *p = (const char *)skiptowhite(arg);
- if (*p != NUL) { // Past first word.
- xp->xp_pattern = skipwhite(p);
- if (*skiptowhite(xp->xp_pattern) != NUL) {
- xp->xp_context = EXPAND_NOTHING;
- } else if (STRNICMP(arg, "case", p - arg) == 0) {
- expand_what = EXP_CASE;
- } else if (STRNICMP(arg, "spell", p - arg) == 0) {
- expand_what = EXP_SPELL;
- } else if (STRNICMP(arg, "sync", p - arg) == 0) {
- expand_what = EXP_SYNC;
- } else if (STRNICMP(arg, "list", p - arg) == 0) {
- p = skipwhite(p);
- if (*p == '@') {
- expand_what = EXP_CLUSTER;
- } else {
- xp->xp_context = EXPAND_HIGHLIGHT;
- }
- } else if (STRNICMP(arg, "keyword", p - arg) == 0
- || STRNICMP(arg, "region", p - arg) == 0
- || STRNICMP(arg, "match", p - arg) == 0) {
- xp->xp_context = EXPAND_HIGHLIGHT;
- } else {
- xp->xp_context = EXPAND_NOTHING;
- }
+ const char *p = (const char *)skiptowhite(arg);
+ if (*p == NUL) {
+ return;
+ }
+
+ // past first world
+ xp->xp_pattern = skipwhite(p);
+ if (*skiptowhite(xp->xp_pattern) != NUL) {
+ xp->xp_context = EXPAND_NOTHING;
+ } else if (STRNICMP(arg, "case", p - arg) == 0) {
+ expand_what = EXP_CASE;
+ } else if (STRNICMP(arg, "spell", p - arg) == 0) {
+ expand_what = EXP_SPELL;
+ } else if (STRNICMP(arg, "sync", p - arg) == 0) {
+ expand_what = EXP_SYNC;
+ } else if (STRNICMP(arg, "list", p - arg) == 0) {
+ p = skipwhite(p);
+ if (*p == '@') {
+ expand_what = EXP_CLUSTER;
+ } else {
+ xp->xp_context = EXPAND_HIGHLIGHT;
}
+ } else if (STRNICMP(arg, "keyword", p - arg) == 0
+ || STRNICMP(arg, "region", p - arg) == 0
+ || STRNICMP(arg, "match", p - arg) == 0) {
+ xp->xp_context = EXPAND_HIGHLIGHT;
+ } else {
+ xp->xp_context = EXPAND_NOTHING;
}
}
@@ -5677,7 +5687,7 @@ static void syntime_report(void)
msg_puts(profile_msg(p->average));
msg_puts(" ");
msg_advance(50);
- msg_outtrans((char *)highlight_group_name(p->id - 1));
+ msg_outtrans(highlight_group_name(p->id - 1));
msg_puts(" ");
msg_advance(69);
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index 73aa6eb9ca..42618e8924 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -210,22 +210,20 @@ static Callback tfu_cb; // 'tagfunc' callback function
/// Reads the 'tagfunc' option value and convert that to a callback value.
/// Invoked when the 'tagfunc' option is set. The option value can be a name of
/// a function (string), or function(<name>) or funcref(<name>) or a lambda.
-int set_tagfunc_option(void)
+void set_tagfunc_option(char **errmsg)
{
callback_free(&tfu_cb);
callback_free(&curbuf->b_tfu_cb);
if (*curbuf->b_p_tfu == NUL) {
- return OK;
+ return;
}
if (option_set_callback_func(curbuf->b_p_tfu, &tfu_cb) == FAIL) {
- return FAIL;
+ *errmsg = e_invarg;
}
callback_copy(&curbuf->b_tfu_cb, &tfu_cb);
-
- return OK;
}
#if defined(EXITFREE)
@@ -1019,7 +1017,7 @@ static int add_llist_tags(char *tag, int num_matches, char **matches)
// Get the line number or the search pattern used to locate
// the tag.
lnum = 0;
- if (isdigit(*tagp.command)) {
+ if (isdigit((uint8_t)(*tagp.command))) {
// Line number is used to locate the tag
lnum = atol(tagp.command);
} else {
@@ -1199,7 +1197,7 @@ static void prepare_pats(pat_T *pats, int has_re)
} else {
for (pats->headlen = 0; pats->head[pats->headlen] != NUL; pats->headlen++) {
if (vim_strchr(magic_isset() ? ".[~*\\$" : "\\$",
- pats->head[pats->headlen]) != NULL) {
+ (uint8_t)pats->head[pats->headlen]) != NULL) {
break;
}
}
@@ -2078,10 +2076,10 @@ static void findtags_add_match(findtags_state_T *st, tagptrs_T *tagpp, findtags_
// the part that matters for comparing, more bytes may
// follow after it. E.g. help tags store the priority
// after the NUL.
- *hash = hash_hash((char_u *)mfp);
+ *hash = hash_hash(mfp);
hi = hash_lookup(&st->ht_match[mtt], (const char *)mfp, strlen(mfp), *hash);
if (HASHITEM_EMPTY(hi)) {
- hash_add_item(&st->ht_match[mtt], hi, (char_u *)mfp, *hash);
+ hash_add_item(&st->ht_match[mtt], hi, mfp, *hash);
GA_APPEND(char *, &st->ga_match[mtt], mfp);
st->match_count++;
} else {
@@ -2563,7 +2561,7 @@ int get_tagfname(tagname_T *tnp, int first, char *buf)
if (first) {
// Init. We make a copy of 'tags', because autocommands may change
// the value without notifying us.
- tnp->tn_tags = xstrdup((*curbuf->b_p_tags != NUL) ? curbuf->b_p_tags : (char *)p_tags);
+ tnp->tn_tags = xstrdup((*curbuf->b_p_tags != NUL) ? curbuf->b_p_tags : p_tags);
tnp->tn_np = tnp->tn_tags;
}
@@ -2573,7 +2571,7 @@ int get_tagfname(tagname_T *tnp, int first, char *buf)
// tnp->tn_did_filefind_init == true: find next file in this part.
for (;;) {
if (tnp->tn_did_filefind_init) {
- fname = (char *)vim_findfile(tnp->tn_search_ctx);
+ fname = vim_findfile(tnp->tn_search_ctx);
if (fname != NULL) {
break;
}
@@ -2593,7 +2591,7 @@ int get_tagfname(tagname_T *tnp, int first, char *buf)
buf[0] = NUL;
(void)copy_option_part(&tnp->tn_np, buf, MAXPATHL - 1, " ,");
- r_ptr = (char *)vim_findfile_stopdir(buf);
+ r_ptr = vim_findfile_stopdir(buf);
// move the filename one char forward and truncate the
// filepath with a NUL
filename = path_tail(buf);
@@ -2734,55 +2732,57 @@ static int parse_match(char *lbuf, tagptrs_T *tagp)
tagp->tagline = 0;
tagp->command_end = NULL;
- if (retval == OK) {
- // Try to find a kind field: "kind:<kind>" or just "<kind>"
- p = tagp->command;
- if (find_extra(&p) == OK) {
- tagp->command_end = p;
- if (p > tagp->command && p[-1] == '|') {
- tagp->command_end = p - 1; // drop trailing bar
- }
- p += 2; // skip ";\""
- if (*p++ == TAB) {
- // Accept ASCII alphabetic kind characters and any multi-byte
- // character.
- while (ASCII_ISALPHA(*p) || utfc_ptr2len(p) > 1) {
- if (strncmp(p, "kind:", 5) == 0) {
- tagp->tagkind = p + 5;
- } else if (strncmp(p, "user_data:", 10) == 0) {
- tagp->user_data = p + 10;
- } else if (strncmp(p, "line:", 5) == 0) {
- tagp->tagline = atoi(p + 5);
- }
- if (tagp->tagkind != NULL && tagp->user_data != NULL) {
- break;
- }
+ if (retval != OK) {
+ return retval;
+ }
- pc = vim_strchr(p, ':');
- pt = vim_strchr(p, '\t');
- if (pc == NULL || (pt != NULL && pc > pt)) {
- tagp->tagkind = p;
- }
- if (pt == NULL) {
- break;
- }
- p = pt;
- MB_PTR_ADV(p);
+ // Try to find a kind field: "kind:<kind>" or just "<kind>"
+ p = tagp->command;
+ if (find_extra(&p) == OK) {
+ tagp->command_end = p;
+ if (p > tagp->command && p[-1] == '|') {
+ tagp->command_end = p - 1; // drop trailing bar
+ }
+ p += 2; // skip ";\""
+ if (*p++ == TAB) {
+ // Accept ASCII alphabetic kind characters and any multi-byte
+ // character.
+ while (ASCII_ISALPHA(*p) || utfc_ptr2len(p) > 1) {
+ if (strncmp(p, "kind:", 5) == 0) {
+ tagp->tagkind = p + 5;
+ } else if (strncmp(p, "user_data:", 10) == 0) {
+ tagp->user_data = p + 10;
+ } else if (strncmp(p, "line:", 5) == 0) {
+ tagp->tagline = atoi(p + 5);
+ }
+ if (tagp->tagkind != NULL && tagp->user_data != NULL) {
+ break;
}
+
+ pc = vim_strchr(p, ':');
+ pt = vim_strchr(p, '\t');
+ if (pc == NULL || (pt != NULL && pc > pt)) {
+ tagp->tagkind = p;
+ }
+ if (pt == NULL) {
+ break;
+ }
+ p = pt;
+ MB_PTR_ADV(p);
}
}
- if (tagp->tagkind != NULL) {
- for (p = tagp->tagkind;
- *p && *p != '\t' && *p != '\r' && *p != '\n';
- MB_PTR_ADV(p)) {}
- tagp->tagkind_end = p;
- }
- if (tagp->user_data != NULL) {
- for (p = tagp->user_data;
- *p && *p != '\t' && *p != '\r' && *p != '\n';
- MB_PTR_ADV(p)) {}
- tagp->user_data_end = p;
- }
+ }
+ if (tagp->tagkind != NULL) {
+ for (p = tagp->tagkind;
+ *p && *p != '\t' && *p != '\r' && *p != '\n';
+ MB_PTR_ADV(p)) {}
+ tagp->tagkind_end = p;
+ }
+ if (tagp->user_data != NULL) {
+ for (p = tagp->user_data;
+ *p && *p != '\t' && *p != '\r' && *p != '\n';
+ MB_PTR_ADV(p)) {}
+ tagp->user_data_end = p;
}
return retval;
}
@@ -3331,86 +3331,88 @@ int get_tags(list_T *list, char *pat, char *buf_fname)
ret = find_tags(pat, &num_matches, &matches,
TAG_REGEXP | TAG_NOIC, MAXCOL, buf_fname);
- if (ret == OK && num_matches > 0) {
- for (i = 0; i < num_matches; i++) {
- int parse_result = parse_match(matches[i], &tp);
+ if (ret != OK || num_matches <= 0) {
+ return ret;
+ }
- // Avoid an unused variable warning in release builds.
- (void)parse_result;
- assert(parse_result == OK);
+ for (i = 0; i < num_matches; i++) {
+ int parse_result = parse_match(matches[i], &tp);
- is_static = test_for_static(&tp);
+ // Avoid an unused variable warning in release builds.
+ (void)parse_result;
+ assert(parse_result == OK);
- // Skip pseudo-tag lines.
- if (strncmp(tp.tagname, "!_TAG_", 6) == 0) {
- xfree(matches[i]);
- continue;
- }
+ is_static = test_for_static(&tp);
+
+ // Skip pseudo-tag lines.
+ if (strncmp(tp.tagname, "!_TAG_", 6) == 0) {
+ xfree(matches[i]);
+ continue;
+ }
+
+ dict = tv_dict_alloc();
+ tv_list_append_dict(list, dict);
- dict = tv_dict_alloc();
- tv_list_append_dict(list, dict);
-
- full_fname = tag_full_fname(&tp);
- if (add_tag_field(dict, "name", tp.tagname, tp.tagname_end) == FAIL
- || add_tag_field(dict, "filename", full_fname, NULL) == FAIL
- || add_tag_field(dict, "cmd", tp.command, tp.command_end) == FAIL
- || add_tag_field(dict, "kind", tp.tagkind,
- tp.tagkind ? tp.tagkind_end : NULL) == FAIL
- || tv_dict_add_nr(dict, S_LEN("static"), is_static) == FAIL) {
- ret = FAIL;
- }
-
- xfree(full_fname);
-
- if (tp.command_end != NULL) {
- for (char *p = tp.command_end + 3;
- *p != NUL && *p != '\n' && *p != '\r';
- MB_PTR_ADV(p)) {
- if (p == tp.tagkind
- || (p + 5 == tp.tagkind && strncmp(p, "kind:", 5) == 0)) {
- // skip "kind:<kind>" and "<kind>"
- p = tp.tagkind_end - 1;
- } else if (strncmp(p, "file:", 5) == 0) {
- // skip "file:" (static tag)
- p += 4;
- } else if (!ascii_iswhite(*p)) {
- char *s, *n;
- int len;
-
- // Add extra field as a dict entry. Fields are
- // separated by Tabs.
- n = p;
- while (*p != NUL && *p >= ' ' && *p < 127 && *p != ':') {
+ full_fname = tag_full_fname(&tp);
+ if (add_tag_field(dict, "name", tp.tagname, tp.tagname_end) == FAIL
+ || add_tag_field(dict, "filename", full_fname, NULL) == FAIL
+ || add_tag_field(dict, "cmd", tp.command, tp.command_end) == FAIL
+ || add_tag_field(dict, "kind", tp.tagkind,
+ tp.tagkind ? tp.tagkind_end : NULL) == FAIL
+ || tv_dict_add_nr(dict, S_LEN("static"), is_static) == FAIL) {
+ ret = FAIL;
+ }
+
+ xfree(full_fname);
+
+ if (tp.command_end != NULL) {
+ for (char *p = tp.command_end + 3;
+ *p != NUL && *p != '\n' && *p != '\r';
+ MB_PTR_ADV(p)) {
+ if (p == tp.tagkind
+ || (p + 5 == tp.tagkind && strncmp(p, "kind:", 5) == 0)) {
+ // skip "kind:<kind>" and "<kind>"
+ p = tp.tagkind_end - 1;
+ } else if (strncmp(p, "file:", 5) == 0) {
+ // skip "file:" (static tag)
+ p += 4;
+ } else if (!ascii_iswhite(*p)) {
+ char *s, *n;
+ int len;
+
+ // Add extra field as a dict entry. Fields are
+ // separated by Tabs.
+ n = p;
+ while (*p != NUL && *p >= ' ' && *p < 127 && *p != ':') {
+ p++;
+ }
+ len = (int)(p - n);
+ if (*p == ':' && len > 0) {
+ s = ++p;
+ while (*p != NUL && (uint8_t)(*p) >= ' ') {
p++;
}
- len = (int)(p - n);
- if (*p == ':' && len > 0) {
- s = ++p;
- while (*p != NUL && (uint8_t)(*p) >= ' ') {
- p++;
- }
- n[len] = NUL;
- if (add_tag_field(dict, n, s, p) == FAIL) {
- ret = FAIL;
- }
- n[len] = ':';
- } else {
- // Skip field without colon.
- while (*p != NUL && (uint8_t)(*p) >= ' ') {
- p++;
- }
+ n[len] = NUL;
+ if (add_tag_field(dict, n, s, p) == FAIL) {
+ ret = FAIL;
}
- if (*p == NUL) {
- break;
+ n[len] = ':';
+ } else {
+ // Skip field without colon.
+ while (*p != NUL && (uint8_t)(*p) >= ' ') {
+ p++;
}
}
+ if (*p == NUL) {
+ break;
+ }
}
}
-
- xfree(matches[i]);
}
- xfree(matches);
+
+ xfree(matches[i]);
}
+ xfree(matches);
return ret;
}
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 106e92d43c..a52a34cd66 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -435,7 +435,7 @@ bool terminal_enter(void)
handle_T save_curwin = curwin->handle;
bool save_w_p_cul = curwin->w_p_cul;
char *save_w_p_culopt = NULL;
- char_u save_w_p_culopt_flags = curwin->w_p_culopt_flags;
+ uint8_t save_w_p_culopt_flags = curwin->w_p_culopt_flags;
int save_w_p_cuc = curwin->w_p_cuc;
long save_w_p_so = curwin->w_p_so;
long save_w_p_siso = curwin->w_p_siso;
@@ -718,7 +718,7 @@ void terminal_paste(long count, char **y_array, size_t y_size)
}
vterm_keyboard_start_paste(curbuf->terminal->vt);
size_t buff_len = strlen(y_array[0]);
- char_u *buff = xmalloc(buff_len);
+ char *buff = xmalloc(buff_len);
for (int i = 0; i < count; i++) { // -V756
// feed the lines to the terminal
for (size_t j = 0; j < y_size; j++) {
@@ -731,18 +731,18 @@ void terminal_paste(long count, char **y_array, size_t y_size)
buff = xrealloc(buff, len);
buff_len = len;
}
- char_u *dst = buff;
- char_u *src = (char_u *)y_array[j];
+ char *dst = buff;
+ char *src = y_array[j];
while (*src != '\0') {
- len = (size_t)utf_ptr2len((char *)src);
- int c = utf_ptr2char((char *)src);
+ len = (size_t)utf_ptr2len(src);
+ int c = utf_ptr2char(src);
if (!is_filter_char(c)) {
memcpy(dst, src, len);
dst += len;
}
src += len;
}
- terminal_send(curbuf->terminal, (char *)buff, (size_t)(dst - buff));
+ terminal_send(curbuf->terminal, buff, (size_t)(dst - buff));
}
}
xfree(buff);
diff --git a/src/nvim/testdir/check.vim b/src/nvim/testdir/check.vim
index a188f7afa1..680a59006b 100644
--- a/src/nvim/testdir/check.vim
+++ b/src/nvim/testdir/check.vim
@@ -1,6 +1,8 @@
source shared.vim
source term_util.vim
+command -nargs=1 MissingFeature throw 'Skipped: ' .. <args> .. ' feature missing'
+
" Command to check for the presence of a feature.
command -nargs=1 CheckFeature call CheckFeature(<f-args>)
func CheckFeature(name)
@@ -8,7 +10,7 @@ func CheckFeature(name)
" throw 'Checking for non-existent feature ' .. a:name
" endif
if !has(a:name)
- throw 'Skipped: ' .. a:name .. ' feature missing'
+ MissingFeature a:name
endif
endfunc
diff --git a/src/nvim/testdir/runnvim.sh b/src/nvim/testdir/runnvim.sh
index 322265737a..3a0a94b6bf 100755
--- a/src/nvim/testdir/runnvim.sh
+++ b/src/nvim/testdir/runnvim.sh
@@ -30,6 +30,9 @@ main() {(
. "$CI_DIR/common/suite.sh"
. "$CI_DIR/common/test.sh"
+ # Redirect XDG_CONFIG_HOME so users local config doesn't interfere
+ export XDG_CONFIG_HOME="$root"
+
export VIMRUNTIME="$root/runtime"
if ! "$nvim_prg" \
-u NONE -i NONE \
diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim
index 704ff6ec55..83af0f6be0 100644
--- a/src/nvim/testdir/test_autocmd.vim
+++ b/src/nvim/testdir/test_autocmd.vim
@@ -629,6 +629,7 @@ func Test_WinScrolled_diff()
\ }, event)
call StopVimInTerminal(buf)
+ call delete('XscrollEvent')
endfunc
func Test_WinClosed()
@@ -2918,7 +2919,7 @@ func Test_autocmd_CmdWinEnter()
call term_sendkeys(buf, "q:")
call term_wait(buf)
call term_sendkeys(buf, ":echo b:dummy_var\<cr>")
- call WaitForAssert({-> assert_match('^This is a dummy', term_getline(buf, 6))}, 1000)
+ call WaitForAssert({-> assert_match('^This is a dummy', term_getline(buf, 6))}, 2000)
call term_sendkeys(buf, ":echo &buftype\<cr>")
call WaitForAssert({-> assert_notmatch('^nofile', term_getline(buf, 6))}, 1000)
call term_sendkeys(buf, ":echo winnr\<cr>")
diff --git a/src/nvim/testdir/test_breakindent.vim b/src/nvim/testdir/test_breakindent.vim
index 995683c68c..2e377aa434 100644
--- a/src/nvim/testdir/test_breakindent.vim
+++ b/src/nvim/testdir/test_breakindent.vim
@@ -856,7 +856,7 @@ func Test_breakindent20_list()
" check formatlistpat indent with different list level
" showbreak and sbr
- setl briopt=min:5,sbr,list:-1,shift:2
+ setl briopt=min:5,sbr,list:-1
setl showbreak=>
redraw!
let expect = [
@@ -869,6 +869,44 @@ func Test_breakindent20_list()
\ ]
let lines = s:screen_lines2(1, 6, 20)
call s:compare_lines(expect, lines)
+
+ " check formatlistpat indent with different list level
+ " showbreak sbr and shift
+ setl briopt=min:5,sbr,list:-1,shift:2
+ setl showbreak=>
+ redraw!
+ let expect = [
+ \ "* Congress shall ",
+ \ "> make no law ",
+ \ "*** Congress shall ",
+ \ "> make no law ",
+ \ "**** Congress shall ",
+ \ "> make no law ",
+ \ ]
+ let lines = s:screen_lines2(1, 6, 20)
+ call s:compare_lines(expect, lines)
+
+ " check breakindent works if breakindentopt=list:-1
+ " for a non list content
+ %delete _
+ call setline(1, [' Congress shall make no law',
+ \ ' Congress shall make no law',
+ \ ' Congress shall make no law'])
+ norm! 1gg
+ setl briopt=min:5,list:-1
+ setl showbreak=
+ redraw!
+ let expect = [
+ \ " Congress shall ",
+ \ " make no law ",
+ \ " Congress shall ",
+ \ " make no law ",
+ \ " Congress shall ",
+ \ " make no law ",
+ \ ]
+ let lines = s:screen_lines2(1, 6, 20)
+ call s:compare_lines(expect, lines)
+
call s:close_windows('set breakindent& briopt& linebreak& list& listchars& showbreak&')
endfunc
diff --git a/src/nvim/testdir/test_buffer.vim b/src/nvim/testdir/test_buffer.vim
index 549aa691c8..9220cc17b9 100644
--- a/src/nvim/testdir/test_buffer.vim
+++ b/src/nvim/testdir/test_buffer.vim
@@ -423,6 +423,12 @@ func Test_buf_pattern_invalid()
vsplit 00000000000000000000000000
silent! buf [0--]\&\zs*\zs*e
bwipe!
+
+ " similar case with different code path
+ split 0
+ edit ÿ
+ silent! buf [0--]\&\zs*\zs*0
+ bwipe!
endfunc
" Test for the 'maxmem' and 'maxmemtot' options
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index 74a5d99ef9..cf1d56ae38 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -151,6 +151,14 @@ func Test_complete_wildmenu()
call assert_equal('"e Xdir1/Xdir2/1', @:)
cunmap <F2>
+ " Test for canceling the wild menu by pressing <PageDown> or <PageUp>.
+ " After this pressing <Left> or <Right> should not change the selection.
+ call feedkeys(":sign \<Tab>\<PageDown>\<Left>\<Right>\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"sign define', @:)
+ call histadd('cmd', 'TestWildMenu')
+ call feedkeys(":sign \<Tab>\<PageUp>\<Left>\<Right>\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"TestWildMenu', @:)
+
" cleanup
%bwipe
call delete('Xdir1', 'rf')
@@ -421,6 +429,7 @@ func Test_getcompletion()
call assert_true(matchcount > 0)
let matchcount = len(getcompletion('File.', 'menu'))
call assert_true(matchcount > 0)
+ source $VIMRUNTIME/delmenu.vim
endif
let l = getcompletion('v:n', 'var')
@@ -642,6 +651,22 @@ func Test_getcompletion()
call assert_fails('call getcompletion("abc", [])', 'E475:')
endfunc
+" Test for getcompletion() with "fuzzy" in 'wildoptions'
+func Test_getcompletion_wildoptions()
+ let save_wildoptions = &wildoptions
+ set wildoptions&
+ let l = getcompletion('space', 'option')
+ call assert_equal([], l)
+ let l = getcompletion('ier', 'command')
+ call assert_equal([], l)
+ set wildoptions=fuzzy
+ let l = getcompletion('space', 'option')
+ call assert_true(index(l, 'backspace') >= 0)
+ let l = getcompletion('ier', 'command')
+ call assert_true(index(l, 'compiler') >= 0)
+ let &wildoptions = save_wildoptions
+endfunc
+
func Test_fullcommand()
let tests = {
\ '': '',
@@ -2198,7 +2223,8 @@ func Test_wildmenu_dirstack()
endfunc
" Test for recalling newer or older cmdline from history with <Up>, <Down>,
-" <S-Up>, <S-Down>, <PageUp>, <PageDown>, <C-p>, or <C-n>.
+" <S-Up>, <S-Down>, <PageUp>, <PageDown>, <kPageUp>, <kPageDown>, <C-p>, or
+" <C-n>.
func Test_recalling_cmdline()
CheckFeature cmdline_hist
@@ -2206,17 +2232,18 @@ func Test_recalling_cmdline()
cnoremap <Plug>(save-cmdline) <Cmd>let g:cmdlines += [getcmdline()]<CR>
let histories = [
- \ {'name': 'cmd', 'enter': ':', 'exit': "\<Esc>"},
- \ {'name': 'search', 'enter': '/', 'exit': "\<Esc>"},
- \ {'name': 'expr', 'enter': ":\<C-r>=", 'exit': "\<Esc>\<Esc>"},
- \ {'name': 'input', 'enter': ":call input('')\<CR>", 'exit': "\<CR>"},
+ \ #{name: 'cmd', enter: ':', exit: "\<Esc>"},
+ \ #{name: 'search', enter: '/', exit: "\<Esc>"},
+ \ #{name: 'expr', enter: ":\<C-r>=", exit: "\<Esc>\<Esc>"},
+ \ #{name: 'input', enter: ":call input('')\<CR>", exit: "\<CR>"},
"\ TODO: {'name': 'debug', ...}
\]
let keypairs = [
- \ {'older': "\<Up>", 'newer': "\<Down>", 'prefixmatch': v:true},
- \ {'older': "\<S-Up>", 'newer': "\<S-Down>", 'prefixmatch': v:false},
- \ {'older': "\<PageUp>", 'newer': "\<PageDown>", 'prefixmatch': v:false},
- \ {'older': "\<C-p>", 'newer': "\<C-n>", 'prefixmatch': v:false},
+ \ #{older: "\<Up>", newer: "\<Down>", prefixmatch: v:true},
+ \ #{older: "\<S-Up>", newer: "\<S-Down>", prefixmatch: v:false},
+ \ #{older: "\<PageUp>", newer: "\<PageDown>", prefixmatch: v:false},
+ \ #{older: "\<kPageUp>", newer: "\<kPageDown>", prefixmatch: v:false},
+ \ #{older: "\<C-p>", newer: "\<C-n>", prefixmatch: v:false},
\]
let prefix = 'vi'
for h in histories
@@ -2331,6 +2358,11 @@ func Test_wildmenu_pum()
set tabline=%!MyTabLine()
set showtabline=2
endfunc
+
+ func DoFeedKeys()
+ let &wildcharm = char2nr("\t")
+ call feedkeys(":edit $VIMRUNTIME/\<Tab>\<Left>\<C-U>ab\<Tab>")
+ endfunc
[CODE]
call writefile(commands, 'Xtest')
@@ -2528,6 +2560,34 @@ func Test_wildmenu_pum()
call term_sendkeys(buf, "\<Esc>")
call VerifyScreenDump(buf, 'Test_wildmenu_pum_40', {})
+ " popup is cleared also when 'lazyredraw' is set
+ call term_sendkeys(buf, ":set showtabline=1 laststatus=1 lazyredraw\<CR>")
+ call term_sendkeys(buf, ":call DoFeedKeys()\<CR>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_41', {})
+ call term_sendkeys(buf, "\<Esc>")
+
+ " Pressing <PageDown> should scroll the menu downward
+ call term_sendkeys(buf, ":sign \<Tab>\<PageDown>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_42', {})
+ call term_sendkeys(buf, "\<PageDown>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_43', {})
+ call term_sendkeys(buf, "\<PageDown>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_44', {})
+ call term_sendkeys(buf, "\<PageDown>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_45', {})
+ call term_sendkeys(buf, "\<C-U>sign \<Tab>\<Down>\<Down>\<PageDown>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_46', {})
+
+ " Pressing <PageUp> should scroll the menu upward
+ call term_sendkeys(buf, "\<C-U>sign \<Tab>\<PageUp>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_47', {})
+ call term_sendkeys(buf, "\<PageUp>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_48', {})
+ call term_sendkeys(buf, "\<PageUp>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_49', {})
+ call term_sendkeys(buf, "\<PageUp>")
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_50', {})
+
call term_sendkeys(buf, "\<C-U>\<CR>")
call StopVimInTerminal(buf)
call delete('Xtest')
@@ -2551,6 +2611,30 @@ func Test_wildmenumode_with_pum()
cunmap <F2>
endfunc
+" Test for opening the cmdline completion popup menu from the terminal window.
+" The popup menu should be positioned correctly over the status line of the
+" bottom-most window.
+func Test_wildmenu_pum_from_terminal()
+ CheckRunVimInTerminal
+ let python = PythonProg()
+ call CheckPython(python)
+
+ %bw!
+ let cmds = ['set wildmenu wildoptions=pum']
+ let pcmd = python .. ' -c "import sys; sys.stdout.write(sys.stdin.read())"'
+ call add(cmds, "call term_start('" .. pcmd .. "')")
+ call writefile(cmds, 'Xtest')
+ let buf = RunVimInTerminal('-S Xtest', #{rows: 10})
+ call term_sendkeys(buf, "\r\r\r")
+ call term_wait(buf)
+ call term_sendkeys(buf, "\<C-W>:sign \<Tab>")
+ call term_wait(buf)
+ call VerifyScreenDump(buf, 'Test_wildmenu_pum_term_01', {})
+ call term_wait(buf)
+ call StopVimInTerminal(buf)
+ call delete('Xtest')
+endfunc
+
func Test_wildmenu_pum_clear_entries()
CheckRunVimInTerminal
@@ -2611,6 +2695,747 @@ func Test_cmdline_complete_dlist()
call assert_equal("\"dlist 10 /pat/ | chistory", @:)
endfunc
+" argument list (only for :argdel) fuzzy completion
+func Test_fuzzy_completion_arglist()
+ argadd change.py count.py charge.py
+ set wildoptions&
+ call feedkeys(":argdel cge\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"argdel cge', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":argdel cge\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"argdel change.py charge.py', @:)
+ %argdelete
+ set wildoptions&
+endfunc
+
+" autocmd group name fuzzy completion
+func Test_fuzzy_completion_autocmd()
+ set wildoptions&
+ augroup MyFuzzyGroup
+ augroup END
+ call feedkeys(":augroup mfg\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"augroup mfg', @:)
+ call feedkeys(":augroup My*p\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"augroup MyFuzzyGroup', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":augroup mfg\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"augroup MyFuzzyGroup', @:)
+ call feedkeys(":augroup My*p\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"augroup My*p', @:)
+ augroup! MyFuzzyGroup
+ set wildoptions&
+endfunc
+
+" buffer name fuzzy completion
+func Test_fuzzy_completion_bufname()
+ set wildoptions&
+ " Use a long name to reduce the risk of matching a random directory name
+ edit SomeRandomFileWithLetters.txt
+ enew
+ call feedkeys(":b SRFWL\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"b SRFWL', @:)
+ call feedkeys(":b S*FileWithLetters.txt\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"b SomeRandomFileWithLetters.txt', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":b SRFWL\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"b SomeRandomFileWithLetters.txt', @:)
+ call feedkeys(":b S*FileWithLetters.txt\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"b S*FileWithLetters.txt', @:)
+ %bw!
+ set wildoptions&
+endfunc
+
+" buffer name (full path) fuzzy completion
+func Test_fuzzy_completion_bufname_fullpath()
+ CheckUnix
+ set wildoptions&
+ call mkdir('Xcmd/Xstate/Xfile.js', 'p')
+ edit Xcmd/Xstate/Xfile.js
+ cd Xcmd/Xstate
+ enew
+ call feedkeys(":b CmdStateFile\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"b CmdStateFile', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":b CmdStateFile\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_match('Xcmd/Xstate/Xfile.js$', @:)
+ cd -
+ call delete('Xcmd', 'rf')
+ set wildoptions&
+endfunc
+
+" :behave suboptions fuzzy completion
+func Test_fuzzy_completion_behave()
+ set wildoptions&
+ call feedkeys(":behave xm\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"behave xm', @:)
+ call feedkeys(":behave xt*m\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"behave xterm', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":behave xm\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"behave xterm', @:)
+ call feedkeys(":behave xt*m\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"behave xt*m', @:)
+ let g:Sline = ''
+ call feedkeys(":behave win\<C-D>\<F4>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('mswin', g:Sline)
+ call assert_equal('"behave win', @:)
+ set wildoptions&
+endfunc
+
+" " colorscheme name fuzzy completion - NOT supported
+" func Test_fuzzy_completion_colorscheme()
+" endfunc
+
+" built-in command name fuzzy completion
+func Test_fuzzy_completion_cmdname()
+ set wildoptions&
+ call feedkeys(":sbwin\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"sbwin', @:)
+ call feedkeys(":sbr*d\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"sbrewind', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":sbwin\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"sbrewind', @:)
+ call feedkeys(":sbr*d\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"sbr*d', @:)
+ set wildoptions&
+endfunc
+
+" " compiler name fuzzy completion - NOT supported
+" func Test_fuzzy_completion_compiler()
+" endfunc
+
+" :cscope suboptions fuzzy completion
+func Test_fuzzy_completion_cscope()
+ CheckFeature cscope
+ set wildoptions&
+ call feedkeys(":cscope ret\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"cscope ret', @:)
+ call feedkeys(":cscope re*t\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"cscope reset', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":cscope ret\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"cscope reset', @:)
+ call feedkeys(":cscope re*t\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"cscope re*t', @:)
+ set wildoptions&
+endfunc
+
+" :diffget/:diffput buffer name fuzzy completion
+func Test_fuzzy_completion_diff()
+ new SomeBuffer
+ diffthis
+ new OtherBuffer
+ diffthis
+ set wildoptions&
+ call feedkeys(":diffget sbuf\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"diffget sbuf', @:)
+ call feedkeys(":diffput sbuf\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"diffput sbuf', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":diffget sbuf\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"diffget SomeBuffer', @:)
+ call feedkeys(":diffput sbuf\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"diffput SomeBuffer', @:)
+ %bw!
+ set wildoptions&
+endfunc
+
+" " directory name fuzzy completion - NOT supported
+" func Test_fuzzy_completion_dirname()
+" endfunc
+
+" environment variable name fuzzy completion
+func Test_fuzzy_completion_env()
+ set wildoptions&
+ call feedkeys(":echo $VUT\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"echo $VUT', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":echo $VUT\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"echo $VIMRUNTIME', @:)
+ set wildoptions&
+endfunc
+
+" autocmd event fuzzy completion
+func Test_fuzzy_completion_autocmd_event()
+ set wildoptions&
+ call feedkeys(":autocmd BWout\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"autocmd BWout', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":autocmd BWout\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"autocmd BufWipeout', @:)
+ set wildoptions&
+endfunc
+
+" vim expression fuzzy completion
+func Test_fuzzy_completion_expr()
+ let g:PerPlaceCount = 10
+ set wildoptions&
+ call feedkeys(":let c = ppc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"let c = ppc', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":let c = ppc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"let c = PerPlaceCount', @:)
+ set wildoptions&
+endfunc
+
+" " file name fuzzy completion - NOT supported
+" func Test_fuzzy_completion_filename()
+" endfunc
+
+" " files in path fuzzy completion - NOT supported
+" func Test_fuzzy_completion_filesinpath()
+" endfunc
+
+" " filetype name fuzzy completion - NOT supported
+" func Test_fuzzy_completion_filetype()
+" endfunc
+
+" user defined function name completion
+func Test_fuzzy_completion_userdefined_func()
+ set wildoptions&
+ call feedkeys(":call Test_f_u_f\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"call Test_f_u_f', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":call Test_f_u_f\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"call Test_fuzzy_completion_userdefined_func()', @:)
+ set wildoptions&
+endfunc
+
+" <SNR> functions should be sorted to the end
+func Test_fuzzy_completion_userdefined_snr_func()
+ func s:Sendmail()
+ endfunc
+ func SendSomemail()
+ endfunc
+ func S1e2n3dmail()
+ endfunc
+ set wildoptions=fuzzy
+ call feedkeys(":call sendmail\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"call SendSomemail() S1e2n3dmail() '
+ \ .. expand("<SID>") .. 'Sendmail()', @:)
+ set wildoptions&
+ delfunc s:Sendmail
+ delfunc SendSomemail
+ delfunc S1e2n3dmail
+endfunc
+
+" user defined command name completion
+func Test_fuzzy_completion_userdefined_cmd()
+ set wildoptions&
+ call feedkeys(":MsFeat\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"MsFeat', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":MsFeat\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"MissingFeature', @:)
+ set wildoptions&
+endfunc
+
+" " :help tag fuzzy completion - NOT supported
+" func Test_fuzzy_completion_helptag()
+" endfunc
+
+" highlight group name fuzzy completion
+func Test_fuzzy_completion_hlgroup()
+ set wildoptions&
+ call feedkeys(":highlight SKey\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"highlight SKey', @:)
+ call feedkeys(":highlight Sp*Key\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"highlight SpecialKey', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":highlight SKey\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"highlight SpecialKey', @:)
+ call feedkeys(":highlight Sp*Key\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"highlight Sp*Key', @:)
+ set wildoptions&
+endfunc
+
+" :history suboptions fuzzy completion
+func Test_fuzzy_completion_history()
+ set wildoptions&
+ call feedkeys(":history dg\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"history dg', @:)
+ call feedkeys(":history se*h\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"history search', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":history dg\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"history debug', @:)
+ call feedkeys(":history se*h\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"history se*h', @:)
+ set wildoptions&
+endfunc
+
+" :language locale name fuzzy completion
+func Test_fuzzy_completion_lang()
+ CheckUnix
+ set wildoptions&
+ call feedkeys(":lang psx\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"lang psx', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":lang psx\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"lang POSIX', @:)
+ set wildoptions&
+endfunc
+
+" :mapclear buffer argument fuzzy completion
+func Test_fuzzy_completion_mapclear()
+ set wildoptions&
+ call feedkeys(":mapclear buf\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"mapclear buf', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":mapclear buf\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"mapclear <buffer>', @:)
+ set wildoptions&
+endfunc
+
+" map name fuzzy completion
+func Test_fuzzy_completion_mapname()
+ " test regex completion works
+ set wildoptions=fuzzy
+ call feedkeys(":cnoremap <ex\<Tab> <esc> \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"cnoremap <expr> <esc> \<Tab>", @:)
+ nmap <plug>MyLongMap :p<CR>
+ call feedkeys(":nmap MLM\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"nmap <Plug>MyLongMap", @:)
+ call feedkeys(":nmap MLM \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"nmap MLM \t", @:)
+ call feedkeys(":nmap <F2> one two \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"nmap <F2> one two \t", @:)
+ " duplicate entries should be removed
+ vmap <plug>MyLongMap :<C-U>#<CR>
+ call feedkeys(":nmap MLM\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"nmap <Plug>MyLongMap", @:)
+ nunmap <plug>MyLongMap
+ vunmap <plug>MyLongMap
+ call feedkeys(":nmap ABC\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"nmap ABC\t", @:)
+ " results should be sorted by best match
+ nmap <Plug>format :
+ nmap <Plug>goformat :
+ nmap <Plug>TestFOrmat :
+ nmap <Plug>fendoff :
+ nmap <Plug>state :
+ nmap <Plug>FendingOff :
+ call feedkeys(":nmap <Plug>fo\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"nmap <Plug>format <Plug>TestFOrmat <Plug>FendingOff <Plug>goformat <Plug>fendoff", @:)
+ nunmap <Plug>format
+ nunmap <Plug>goformat
+ nunmap <Plug>TestFOrmat
+ nunmap <Plug>fendoff
+ nunmap <Plug>state
+ nunmap <Plug>FendingOff
+ set wildoptions&
+endfunc
+
+" abbreviation fuzzy completion
+func Test_fuzzy_completion_abbr()
+ set wildoptions=fuzzy
+ call feedkeys(":iabbr wait\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"iabbr <nowait>", @:)
+ iabbr WaitForCompletion WFC
+ call feedkeys(":iabbr fcl\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"iabbr WaitForCompletion", @:)
+ call feedkeys(":iabbr a1z\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"iabbr a1z\t", @:)
+
+ iunabbrev WaitForCompletion
+ set wildoptions&
+endfunc
+
+" menu name fuzzy completion
+func Test_fuzzy_completion_menu()
+ CheckFeature menu
+
+ source $VIMRUNTIME/menu.vim
+ set wildoptions&
+ call feedkeys(":menu pup\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"menu pup', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":menu pup\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"menu PopUp.', @:)
+
+ set wildoptions&
+ source $VIMRUNTIME/delmenu.vim
+endfunc
+
+" :messages suboptions fuzzy completion
+func Test_fuzzy_completion_messages()
+ set wildoptions&
+ call feedkeys(":messages clr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"messages clr', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":messages clr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"messages clear', @:)
+ set wildoptions&
+endfunc
+
+" :set option name fuzzy completion
+func Test_fuzzy_completion_option()
+ set wildoptions&
+ call feedkeys(":set brkopt\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set brkopt', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":set brkopt\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set breakindentopt', @:)
+ set wildoptions&
+ call feedkeys(":set fixeol\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set fixendofline', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":set fixeol\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set fixendofline', @:)
+ set wildoptions&
+endfunc
+
+" :set <term_option>
+func Test_fuzzy_completion_term_option()
+ throw 'Skipped: Nvim does not support term options'
+ set wildoptions&
+ call feedkeys(":set t_E\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set t_EC', @:)
+ call feedkeys(":set <t_E\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set <t_EC>', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":set t_E\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set t_EC', @:)
+ call feedkeys(":set <t_E\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set <t_EC>', @:)
+ set wildoptions&
+endfunc
+
+" " :packadd directory name fuzzy completion - NOT supported
+" func Test_fuzzy_completion_packadd()
+" endfunc
+
+" " shell command name fuzzy completion - NOT supported
+" func Test_fuzzy_completion_shellcmd()
+" endfunc
+
+" :sign suboptions fuzzy completion
+func Test_fuzzy_completion_sign()
+ set wildoptions&
+ call feedkeys(":sign ufe\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"sign ufe', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":sign ufe\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"sign undefine', @:)
+ set wildoptions&
+endfunc
+
+" :syntax suboptions fuzzy completion
+func Test_fuzzy_completion_syntax_cmd()
+ set wildoptions&
+ call feedkeys(":syntax kwd\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"syntax kwd', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":syntax kwd\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"syntax keyword', @:)
+ set wildoptions&
+endfunc
+
+" syntax group name fuzzy completion
+func Test_fuzzy_completion_syntax_group()
+ set wildoptions&
+ call feedkeys(":syntax list mpar\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"syntax list mpar', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":syntax list mpar\<Tab>\<C-B>\"\<CR>", 'tx')
+ " Fuzzy match prefers NvimParenthesis over MatchParen
+ " call assert_equal('"syntax list MatchParen', @:)
+ call assert_equal('"syntax list NvimParenthesis', @:)
+ set wildoptions&
+endfunc
+
+" :syntime suboptions fuzzy completion
+func Test_fuzzy_completion_syntime()
+ CheckFeature profile
+ set wildoptions&
+ call feedkeys(":syntime clr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"syntime clr', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":syntime clr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"syntime clear', @:)
+ set wildoptions&
+endfunc
+
+" " tag name fuzzy completion - NOT supported
+" func Test_fuzzy_completion_tagname()
+" endfunc
+
+" " tag name and file fuzzy completion - NOT supported
+" func Test_fuzzy_completion_tagfile()
+" endfunc
+
+" " user names fuzzy completion - how to test this functionality?
+" func Test_fuzzy_completion_username()
+" endfunc
+
+" user defined variable name fuzzy completion
+func Test_fuzzy_completion_userdefined_var()
+ let g:SomeVariable=10
+ set wildoptions&
+ call feedkeys(":let SVar\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"let SVar', @:)
+ set wildoptions=fuzzy
+ call feedkeys(":let SVar\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"let SomeVariable', @:)
+ set wildoptions&
+endfunc
+
+" Test for sorting the results by the best match
+func Test_fuzzy_completion_cmd_sort_results()
+ %bw!
+ command T123format :
+ command T123goformat :
+ command T123TestFOrmat :
+ command T123fendoff :
+ command T123state :
+ command T123FendingOff :
+ set wildoptions=fuzzy
+ call feedkeys(":T123fo\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"T123format T123TestFOrmat T123FendingOff T123goformat T123fendoff', @:)
+ delcommand T123format
+ delcommand T123goformat
+ delcommand T123TestFOrmat
+ delcommand T123fendoff
+ delcommand T123state
+ delcommand T123FendingOff
+ %bw
+ set wildoptions&
+endfunc
+
+" Test for fuzzy completion of a command with lower case letters and a number
+func Test_fuzzy_completion_cmd_alnum()
+ command Foo2Bar :
+ set wildoptions=fuzzy
+ call feedkeys(":foo2\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"Foo2Bar', @:)
+ call feedkeys(":foo\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"Foo2Bar', @:)
+ call feedkeys(":bar\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"Foo2Bar', @:)
+ delcommand Foo2Bar
+ set wildoptions&
+endfunc
+
+" Test for command completion for a command starting with 'k'
+func Test_fuzzy_completion_cmd_k()
+ command KillKillKill :
+ set wildoptions&
+ call feedkeys(":killkill\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"killkill\<Tab>", @:)
+ set wildoptions=fuzzy
+ call feedkeys(":killkill\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"KillKillKill', @:)
+ delcom KillKillKill
+ set wildoptions&
+endfunc
+
+" Test for fuzzy completion for user defined custom completion function
+func Test_fuzzy_completion_custom_func()
+ func Tcompl(a, c, p)
+ return "format\ngoformat\nTestFOrmat\nfendoff\nstate"
+ endfunc
+ command -nargs=* -complete=custom,Tcompl Fuzzy :
+ set wildoptions&
+ call feedkeys(":Fuzzy fo\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"Fuzzy format", @:)
+ call feedkeys(":Fuzzy xy\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"Fuzzy xy", @:)
+ call feedkeys(":Fuzzy ttt\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"Fuzzy ttt", @:)
+ set wildoptions=fuzzy
+ call feedkeys(":Fuzzy \<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"Fuzzy format goformat TestFOrmat fendoff state", @:)
+ call feedkeys(":Fuzzy fo\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"Fuzzy format TestFOrmat goformat fendoff", @:)
+ call feedkeys(":Fuzzy xy\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"Fuzzy xy", @:)
+ call feedkeys(":Fuzzy ttt\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"Fuzzy TestFOrmat", @:)
+ delcom Fuzzy
+ set wildoptions&
+endfunc
+
+" Test for :breakadd argument completion
+func Test_cmdline_complete_breakadd()
+ call feedkeys(":breakadd \<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd expr file func here", @:)
+ call feedkeys(":breakadd \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd expr", @:)
+ call feedkeys(":breakadd \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd expr", @:)
+ call feedkeys(":breakadd he\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd here", @:)
+ call feedkeys(":breakadd he\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd here", @:)
+ call feedkeys(":breakadd abc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd abc", @:)
+ call assert_equal(['expr', 'file', 'func', 'here'], getcompletion('', 'breakpoint'))
+ let l = getcompletion('not', 'breakpoint')
+ call assert_equal([], l)
+
+ " Test for :breakadd file [lnum] <file>
+ call writefile([], 'Xscript')
+ call feedkeys(":breakadd file Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd file Xscript", @:)
+ call feedkeys(":breakadd file Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd file Xscript", @:)
+ call feedkeys(":breakadd file 20 Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd file 20 Xscript", @:)
+ call feedkeys(":breakadd file 20 Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd file 20 Xscript", @:)
+ call feedkeys(":breakadd file 20x Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd file 20x Xsc\t", @:)
+ call feedkeys(":breakadd file 20\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd file 20\t", @:)
+ call feedkeys(":breakadd file 20x\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd file 20x\t", @:)
+ call feedkeys(":breakadd file Xscript \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd file Xscript ", @:)
+ call feedkeys(":breakadd file X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd file X1B2C3", @:)
+ call delete('Xscript')
+
+ " Test for :breakadd func [lnum] <function>
+ func Xbreak_func()
+ endfunc
+ call feedkeys(":breakadd func Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd func Xbreak_func", @:)
+ call feedkeys(":breakadd func Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd func Xbreak_func", @:)
+ call feedkeys(":breakadd func 20 Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd func 20 Xbreak_func", @:)
+ call feedkeys(":breakadd func 20 Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd func 20 Xbreak_func", @:)
+ call feedkeys(":breakadd func 20x Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd func 20x Xbr\t", @:)
+ call feedkeys(":breakadd func 20\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd func 20\t", @:)
+ call feedkeys(":breakadd func 20x\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd func 20x\t", @:)
+ call feedkeys(":breakadd func Xbreak_func \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd func Xbreak_func ", @:)
+ call feedkeys(":breakadd func X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd func X1B2C3", @:)
+ delfunc Xbreak_func
+
+ " Test for :breakadd expr <expression>
+ let g:Xtest_var = 10
+ call feedkeys(":breakadd expr Xtest\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd expr Xtest_var", @:)
+ call feedkeys(":breakadd expr Xtest\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd expr Xtest_var", @:)
+ call feedkeys(":breakadd expr Xtest_var \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd expr Xtest_var ", @:)
+ call feedkeys(":breakadd expr X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd expr X1B2C3", @:)
+ unlet g:Xtest_var
+
+ " Test for :breakadd here
+ call feedkeys(":breakadd here Xtest\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd here Xtest", @:)
+ call feedkeys(":breakadd here Xtest\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd here Xtest", @:)
+ call feedkeys(":breakadd here \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakadd here ", @:)
+endfunc
+
+" Test for :breakdel argument completion
+func Test_cmdline_complete_breakdel()
+ call feedkeys(":breakdel \<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file func here", @:)
+ call feedkeys(":breakdel \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file", @:)
+ call feedkeys(":breakdel \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file", @:)
+ call feedkeys(":breakdel he\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel here", @:)
+ call feedkeys(":breakdel he\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel here", @:)
+ call feedkeys(":breakdel abc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel abc", @:)
+
+ " Test for :breakdel file [lnum] <file>
+ call writefile([], 'Xscript')
+ call feedkeys(":breakdel file Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file Xscript", @:)
+ call feedkeys(":breakdel file Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file Xscript", @:)
+ call feedkeys(":breakdel file 20 Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file 20 Xscript", @:)
+ call feedkeys(":breakdel file 20 Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file 20 Xscript", @:)
+ call feedkeys(":breakdel file 20x Xsc\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file 20x Xsc\t", @:)
+ call feedkeys(":breakdel file 20\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file 20\t", @:)
+ call feedkeys(":breakdel file 20x\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file 20x\t", @:)
+ call feedkeys(":breakdel file Xscript \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file Xscript ", @:)
+ call feedkeys(":breakdel file X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel file X1B2C3", @:)
+ call delete('Xscript')
+
+ " Test for :breakdel func [lnum] <function>
+ func Xbreak_func()
+ endfunc
+ call feedkeys(":breakdel func Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel func Xbreak_func", @:)
+ call feedkeys(":breakdel func Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel func Xbreak_func", @:)
+ call feedkeys(":breakdel func 20 Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel func 20 Xbreak_func", @:)
+ call feedkeys(":breakdel func 20 Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel func 20 Xbreak_func", @:)
+ call feedkeys(":breakdel func 20x Xbr\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel func 20x Xbr\t", @:)
+ call feedkeys(":breakdel func 20\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel func 20\t", @:)
+ call feedkeys(":breakdel func 20x\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel func 20x\t", @:)
+ call feedkeys(":breakdel func Xbreak_func \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel func Xbreak_func ", @:)
+ call feedkeys(":breakdel func X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel func X1B2C3", @:)
+ delfunc Xbreak_func
+
+ " Test for :breakdel here
+ call feedkeys(":breakdel here Xtest\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel here Xtest", @:)
+ call feedkeys(":breakdel here Xtest\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel here Xtest", @:)
+ call feedkeys(":breakdel here \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"breakdel here ", @:)
+endfunc
+
+" Test for :scriptnames argument completion
+func Test_cmdline_complete_scriptnames()
+ set wildmenu
+ call writefile(['let a = 1'], 'Xa1b2c3.vim')
+ source Xa1b2c3.vim
+ call feedkeys(":script \<Tab>\<Left>\<Left>\<C-B>\"\<CR>", 'tx')
+ call assert_match("\"script .*Xa1b2c3.vim$", @:)
+ call feedkeys(":script \<Tab>\<Left>\<Left>\<C-B>\"\<CR>", 'tx')
+ call assert_match("\"script .*Xa1b2c3.vim$", @:)
+ call feedkeys(":script b2c3\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"script b2c3", @:)
+ call feedkeys(":script 2\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_match("\"script 2\<Tab>$", @:)
+ call feedkeys(":script \<Tab>\<Left>\<Left> \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_match("\"script .*Xa1b2c3.vim $", @:)
+ call feedkeys(":script \<Tab>\<Left>\<C-B>\"\<CR>", 'tx')
+ call assert_equal("\"script ", @:)
+ call assert_match('Xa1b2c3.vim$', getcompletion('.*Xa1b2.*', 'scriptnames')[0])
+ call assert_equal([], getcompletion('Xa1b2', 'scriptnames'))
+ new
+ call feedkeys(":script \<Tab>\<Left>\<Left>\<CR>", 'tx')
+ call assert_equal('Xa1b2c3.vim', fnamemodify(@%, ':t'))
+ bw!
+ call delete('Xa1b2c3.vim')
+ set wildmenu&
+endfunc
+
" this was going over the end of IObuff
func Test_report_error_with_composing()
let caught = 'no'
@@ -2635,6 +3460,16 @@ func Test_cmdline_complete_substitute_short()
endfor
endfunc
+" Test for :! shell command argument completion
+func Test_cmdline_complete_bang_cmd_argument()
+ set wildoptions=fuzzy
+ call feedkeys(":!vim test_cmdline.\<Tab>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"!vim test_cmdline.vim', @:)
+ set wildoptions&
+ call feedkeys(":!vim test_cmdline.\<Tab>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"!vim test_cmdline.vim', @:)
+endfunc
+
func Check_completion()
call assert_equal('let a', getcmdline())
call assert_equal(6, getcmdpos())
diff --git a/src/nvim/testdir/test_const.vim b/src/nvim/testdir/test_const.vim
index 7f19085b16..4a6c8779dd 100644
--- a/src/nvim/testdir/test_const.vim
+++ b/src/nvim/testdir/test_const.vim
@@ -194,6 +194,14 @@ func Test_lockvar()
if 0 | lockvar x | endif
let x = 'again'
+
+ let val = [1, 2, 3]
+ lockvar 0 val
+ let val[0] = 9
+ call assert_equal([9, 2, 3], val)
+ call add(val, 4)
+ call assert_equal([9, 2, 3, 4], val)
+ call assert_fails('let val = [4, 5, 6]', 'E1122:')
endfunc
diff --git a/src/nvim/testdir/test_cursorline.vim b/src/nvim/testdir/test_cursorline.vim
index 47646125db..70f39a8601 100644
--- a/src/nvim/testdir/test_cursorline.vim
+++ b/src/nvim/testdir/test_cursorline.vim
@@ -319,7 +319,7 @@ func Test_cursorline_cursorbind_horizontal_scroll()
let lines =<< trim END
call setline(1, 'aa bb cc dd ee ff gg hh ii jj kk ll mm' ..
- \ ' nn oo pp qq rr ss tt uu vv ww xx yy zz')
+ \ ' nn oo pp qq rr ss tt uu vv ww xx yy zz')
set nowrap
" The following makes the cursor apparent on the screen dump
set sidescroll=1 cursorcolumn
diff --git a/src/nvim/testdir/test_debugger.vim b/src/nvim/testdir/test_debugger.vim
index 4609b9d2f9..f5177c8fb2 100644
--- a/src/nvim/testdir/test_debugger.vim
+++ b/src/nvim/testdir/test_debugger.vim
@@ -36,7 +36,7 @@ endfunc
" If the expected output argument is supplied, then check for it.
func RunDbgCmd(buf, cmd, ...)
call term_sendkeys(a:buf, a:cmd . "\r")
- call term_wait(a:buf)
+ call term_wait(a:buf, 20)
if a:0 != 0
let options = #{match: 'equal'}
diff --git a/src/nvim/testdir/test_edit.vim b/src/nvim/testdir/test_edit.vim
index fd54f77ccb..89a9179e60 100644
--- a/src/nvim/testdir/test_edit.vim
+++ b/src/nvim/testdir/test_edit.vim
@@ -336,8 +336,23 @@ func Test_edit_11_indentexpr()
endfunc
set indentexpr=s:NewIndentExpr()
call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &indentexpr)
+ call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &g:indentexpr)
set indentexpr=<SID>NewIndentExpr()
call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &indentexpr)
+ call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &g:indentexpr)
+ setlocal indentexpr=
+ setglobal indentexpr=s:NewIndentExpr()
+ call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &g:indentexpr)
+ call assert_equal('', &indentexpr)
+ new
+ call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &indentexpr)
+ bw!
+ setglobal indentexpr=<SID>NewIndentExpr()
+ call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &g:indentexpr)
+ call assert_equal('', &indentexpr)
+ new
+ call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &indentexpr)
+ bw!
set indentexpr&
bw!
diff --git a/src/nvim/testdir/test_filetype.vim b/src/nvim/testdir/test_filetype.vim
index b065df68f7..88c25ab115 100644
--- a/src/nvim/testdir/test_filetype.vim
+++ b/src/nvim/testdir/test_filetype.vim
@@ -98,6 +98,7 @@ let s:filename_checks = {
\ 'cabalconfig': ['cabal.config'],
\ 'cabalproject': ['cabal.project', 'cabal.project.local'],
\ 'calendar': ['calendar', '/.calendar/file', '/share/calendar/any/calendar.file', '/share/calendar/calendar.file', 'any/share/calendar/any/calendar.file', 'any/share/calendar/calendar.file'],
+ \ 'capnp': ['file.capnp'],
\ 'catalog': ['catalog', 'sgml.catalogfile', 'sgml.catalog', 'sgml.catalog-file'],
\ 'cdl': ['file.cdl'],
\ 'cdrdaoconf': ['/etc/cdrdao.conf', '/etc/defaults/cdrdao', '/etc/default/cdrdao', '.cdrdao', 'any/etc/cdrdao.conf', 'any/etc/default/cdrdao', 'any/etc/defaults/cdrdao'],
@@ -122,7 +123,7 @@ let s:filename_checks = {
\ 'conaryrecipe': ['file.recipe'],
\ 'conf': ['auto.master'],
\ 'config': ['configure.in', 'configure.ac', '/etc/hostname.file', 'any/etc/hostname.file'],
- \ 'confini': ['/etc/pacman.conf', 'any/etc/pacman.conf', 'mpv.conf', 'any/.aws/config', 'any/.aws/credentials'],
+ \ 'confini': ['/etc/pacman.conf', 'any/etc/pacman.conf', 'mpv.conf', 'any/.aws/config', 'any/.aws/credentials', 'file.nmconnection'],
\ 'context': ['tex/context/any/file.tex', 'file.mkii', 'file.mkiv', 'file.mkvi', 'file.mkxl', 'file.mklx'],
\ 'cook': ['file.cook'],
\ 'cpp': ['file.cxx', 'file.c++', 'file.hh', 'file.hxx', 'file.hpp', 'file.ipp', 'file.moc', 'file.tcc', 'file.inl', 'file.tlh'],
@@ -180,6 +181,7 @@ let s:filename_checks = {
\ 'elixir': ['file.ex', 'file.exs', 'mix.lock'],
\ 'elm': ['file.elm'],
\ 'elmfilt': ['filter-rules'],
+ \ 'elsa': ['file.lc'],
\ 'elvish': ['file.elv'],
\ 'epuppet': ['file.epp'],
\ 'erlang': ['file.erl', 'file.hrl', 'file.yaws'],
@@ -293,13 +295,14 @@ let s:filename_checks = {
\ 'jq': ['file.jq'],
\ 'jovial': ['file.jov', 'file.j73', 'file.jovial'],
\ 'jproperties': ['file.properties', 'file.properties_xx', 'file.properties_xx_xx', 'some.properties_xx_xx_file', 'org.eclipse.xyz.prefs'],
- \ 'json': ['file.json', 'file.jsonp', 'file.json-patch', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb', '.prettierrc', '.firebaserc', 'file.slnf'],
+ \ 'json': ['file.json', 'file.jsonp', 'file.json-patch', 'file.webmanifest', 'Pipfile.lock', 'file.ipynb', '.prettierrc', '.firebaserc', '.stylelintrc', 'file.slnf'],
\ 'json5': ['file.json5'],
\ 'jsonc': ['file.jsonc', '.babelrc', '.eslintrc', '.jsfmtrc', '.jshintrc', '.hintrc', '.swrc', 'jsconfig.json', 'tsconfig.json', 'tsconfig.test.json', 'tsconfig-test.json'],
\ 'jsonnet': ['file.jsonnet', 'file.libsonnet'],
\ 'jsp': ['file.jsp'],
\ 'julia': ['file.jl'],
\ 'kconfig': ['Kconfig', 'Kconfig.debug', 'Kconfig.file'],
+ \ 'kdl': ['file.kdl'],
\ 'kivy': ['file.kv'],
\ 'kix': ['file.kix'],
\ 'kotlin': ['file.kt', 'file.ktm', 'file.kts'],
@@ -580,6 +583,7 @@ let s:filename_checks = {
\ 'texmf': ['texmf.cnf'],
\ 'text': ['file.text', 'file.txt', 'README', 'LICENSE', 'COPYING', 'AUTHORS', '/usr/share/doc/bash-completion/AUTHORS', '/etc/apt/apt.conf.d/README', '/etc/Muttrc.d/README'],
\ 'tf': ['file.tf', '.tfrc', 'tfrc'],
+ \ 'thrift': ['file.thrift'],
\ 'tidy': ['.tidyrc', 'tidyrc', 'tidy.conf'],
\ 'tilde': ['file.t.html'],
\ 'tla': ['file.tla'],
@@ -653,7 +657,7 @@ let s:filename_checks = {
\ 'xsd': ['file.xsd'],
\ 'xslt': ['file.xsl', 'file.xslt'],
\ 'yacc': ['file.yy', 'file.yxx', 'file.y++'],
- \ 'yaml': ['file.yaml', 'file.yml', '.clang-format', '.clang-tidy'],
+ \ 'yaml': ['file.yaml', 'file.yml', '.clangd', '.clang-format', '.clang-tidy'],
\ 'yang': ['file.yang'],
\ 'z8a': ['file.z8a'],
\ 'zig': ['file.zig'],
diff --git a/src/nvim/testdir/test_fold.vim b/src/nvim/testdir/test_fold.vim
index 130ad9c7e1..9014948fb4 100644
--- a/src/nvim/testdir/test_fold.vim
+++ b/src/nvim/testdir/test_fold.vim
@@ -1305,6 +1305,7 @@ func Test_foldexpr_scriptlocal_func()
set foldmethod=expr foldexpr=s:FoldFunc()
redraw!
call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
+ call assert_equal(expand('<SID>') .. 'FoldFunc()', &g:foldexpr)
call assert_equal(1, g:FoldLnum)
set foldmethod& foldexpr=
bw!
@@ -1314,8 +1315,31 @@ func Test_foldexpr_scriptlocal_func()
set foldmethod=expr foldexpr=<SID>FoldFunc()
redraw!
call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
+ call assert_equal(expand('<SID>') .. 'FoldFunc()', &g:foldexpr)
call assert_equal(1, g:FoldLnum)
- set foldmethod& foldexpr=
+ bw!
+ call setline(1, 'abc')
+ setlocal foldmethod& foldexpr&
+ setglobal foldmethod=expr foldexpr=s:FoldFunc()
+ call assert_equal(expand('<SID>') .. 'FoldFunc()', &g:foldexpr)
+ call assert_equal('0', &foldexpr)
+ enew!
+ call setline(1, 'abc')
+ redraw!
+ call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
+ call assert_equal(1, g:FoldLnum)
+ bw!
+ call setline(1, 'abc')
+ setlocal foldmethod& foldexpr&
+ setglobal foldmethod=expr foldexpr=<SID>FoldFunc()
+ call assert_equal(expand('<SID>') .. 'FoldFunc()', &g:foldexpr)
+ call assert_equal('0', &foldexpr)
+ enew!
+ call setline(1, 'abc')
+ redraw!
+ call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
+ call assert_equal(1, g:FoldLnum)
+ set foldmethod& foldexpr&
delfunc s:FoldFunc
bw!
endfunc
@@ -1329,25 +1353,53 @@ func Test_foldtext_scriptlocal_func()
new | only
call setline(1, range(50))
let g:FoldTextArgs = []
- set foldmethod=manual
set foldtext=s:FoldText()
norm! 4Gzf4j
redraw!
call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
+ call assert_equal(expand('<SID>') .. 'FoldText()', &g:foldtext)
call assert_equal([4, 8], g:FoldTextArgs)
set foldtext&
bw!
new | only
call setline(1, range(50))
let g:FoldTextArgs = []
- set foldmethod=manual
set foldtext=<SID>FoldText()
norm! 8Gzf4j
redraw!
call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
+ call assert_equal(expand('<SID>') .. 'FoldText()', &g:foldtext)
call assert_equal([8, 12], g:FoldTextArgs)
set foldtext&
bw!
+ call setline(1, range(50))
+ let g:FoldTextArgs = []
+ setlocal foldtext&
+ setglobal foldtext=s:FoldText()
+ call assert_equal(expand('<SID>') .. 'FoldText()', &g:foldtext)
+ call assert_equal('foldtext()', &foldtext)
+ enew!
+ call setline(1, range(50))
+ norm! 12Gzf4j
+ redraw!
+ call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
+ call assert_equal([12, 16], g:FoldTextArgs)
+ set foldtext&
+ bw!
+ call setline(1, range(50))
+ let g:FoldTextArgs = []
+ setlocal foldtext&
+ setglobal foldtext=<SID>FoldText()
+ call assert_equal(expand('<SID>') .. 'FoldText()', &g:foldtext)
+ call assert_equal('foldtext()', &foldtext)
+ enew!
+ call setline(1, range(50))
+ norm! 16Gzf4j
+ redraw!
+ call assert_equal(expand('<SID>') .. 'FoldText()', &foldtext)
+ call assert_equal([16, 20], g:FoldTextArgs)
+ set foldtext&
+ bw!
delfunc s:FoldText
endfunc
@@ -1483,4 +1535,17 @@ func Test_indent_with_L_command()
bwipe!
endfunc
+" Make sure that when there is a fold at the bottom of the buffer and a newline
+" character is appended to the line, the fold gets expanded (instead of the new
+" line not being part of the fold).
+func Test_expand_fold_at_bottom_of_buffer()
+ new
+ " create a fold on the only line
+ fold
+ execute "normal A\<CR>"
+ call assert_equal([1, 1], range(1, 2)->map('foldlevel(v:val)'))
+
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_gf.vim b/src/nvim/testdir/test_gf.vim
index e369645328..f09dbd72ce 100644
--- a/src/nvim/testdir/test_gf.vim
+++ b/src/nvim/testdir/test_gf.vim
@@ -234,6 +234,7 @@ func Test_includeexpr_scriptlocal_func()
endfunc
set includeexpr=s:IncludeFunc()
call assert_equal(expand('<SID>') .. 'IncludeFunc()', &includeexpr)
+ call assert_equal(expand('<SID>') .. 'IncludeFunc()', &g:includeexpr)
new | only
call setline(1, 'TestFile1')
let g:IncludeFname = ''
@@ -242,11 +243,35 @@ func Test_includeexpr_scriptlocal_func()
bw!
set includeexpr=<SID>IncludeFunc()
call assert_equal(expand('<SID>') .. 'IncludeFunc()', &includeexpr)
+ call assert_equal(expand('<SID>') .. 'IncludeFunc()', &g:includeexpr)
new | only
call setline(1, 'TestFile2')
let g:IncludeFname = ''
call assert_fails('normal! gf', 'E447:')
call assert_equal('TestFile2', g:IncludeFname)
+ bw!
+ setlocal includeexpr=
+ setglobal includeexpr=s:IncludeFunc()
+ call assert_equal(expand('<SID>') .. 'IncludeFunc()', &g:includeexpr)
+ call assert_equal('', &includeexpr)
+ new
+ call assert_equal(expand('<SID>') .. 'IncludeFunc()', &includeexpr)
+ call setline(1, 'TestFile3')
+ let g:IncludeFname = ''
+ call assert_fails('normal! gf', 'E447:')
+ call assert_equal('TestFile3', g:IncludeFname)
+ bw!
+ setlocal includeexpr=
+ setglobal includeexpr=<SID>IncludeFunc()
+ call assert_equal(expand('<SID>') .. 'IncludeFunc()', &g:includeexpr)
+ call assert_equal('', &includeexpr)
+ new
+ call assert_equal(expand('<SID>') .. 'IncludeFunc()', &includeexpr)
+ call setline(1, 'TestFile4')
+ let g:IncludeFname = ''
+ call assert_fails('normal! gf', 'E447:')
+ call assert_equal('TestFile4', g:IncludeFname)
+ bw!
set includeexpr&
delfunc s:IncludeFunc
bw!
diff --git a/src/nvim/testdir/test_ins_complete.vim b/src/nvim/testdir/test_ins_complete.vim
index 7a9392545e..ec1379a378 100644
--- a/src/nvim/testdir/test_ins_complete.vim
+++ b/src/nvim/testdir/test_ins_complete.vim
@@ -581,6 +581,33 @@ func Test_pum_with_folds_two_tabs()
call delete('Xpumscript')
endfunc
+func Test_pum_with_preview_win()
+ CheckScreendump
+
+ let lines =<< trim END
+ funct Omni_test(findstart, base)
+ if a:findstart
+ return col(".") - 1
+ endif
+ return [#{word: "one", info: "1info"}, #{word: "two", info: "2info"}, #{word: "three", info: "3info"}]
+ endfunc
+ set omnifunc=Omni_test
+ set completeopt+=longest
+ END
+
+ call writefile(lines, 'Xpreviewscript')
+ let buf = RunVimInTerminal('-S Xpreviewscript', #{rows: 12})
+ call term_wait(buf, 100)
+ call term_sendkeys(buf, "Gi\<C-X>\<C-O>")
+ call term_wait(buf, 200)
+ call term_sendkeys(buf, "\<C-N>")
+ call VerifyScreenDump(buf, 'Test_pum_with_preview_win', {})
+
+ call term_sendkeys(buf, "\<Esc>")
+ call StopVimInTerminal(buf)
+ call delete('Xpreviewscript')
+endfunc
+
" Test for inserting the tag search pattern in insert mode
func Test_ins_compl_tag_sft()
call writefile([
diff --git a/src/nvim/testdir/test_listdict.vim b/src/nvim/testdir/test_listdict.vim
index 8d7bede403..9ecd83265a 100644
--- a/src/nvim/testdir/test_listdict.vim
+++ b/src/nvim/testdir/test_listdict.vim
@@ -357,7 +357,7 @@ endfunc
" Locked variables
func Test_list_locked_var()
let expected = [
- \ [['0000-000', 'ppppppp'],
+ \ [['1000-000', 'ppppppF'],
\ ['0000-000', 'ppppppp'],
\ ['0000-000', 'ppppppp']],
\ [['1000-000', 'ppppppF'],
@@ -384,7 +384,7 @@ func Test_list_locked_var()
exe "unlockvar " . depth . " l"
endif
let ps = islocked("l").islocked("l[1]").islocked("l[1][1]").islocked("l[1][1][0]").'-'.islocked("l[2]").islocked("l[2]['6']").islocked("l[2]['6'][7]")
- call assert_equal(expected[depth][u][0], ps)
+ call assert_equal(expected[depth][u][0], ps, 'depth: ' .. depth)
let ps = ''
try
let l[1][1][0] = 99
@@ -428,7 +428,7 @@ func Test_list_locked_var()
catch
let ps .= 'F'
endtry
- call assert_equal(expected[depth][u][1], ps)
+ call assert_equal(expected[depth][u][1], ps, 'depth: ' .. depth)
endfor
endfor
call assert_fails("let x=islocked('a b')", 'E488:')
@@ -441,7 +441,7 @@ endfunc
" Unletting locked variables
func Test_list_locked_var_unlet()
let expected = [
- \ [['0000-000', 'ppppppp'],
+ \ [['1000-000', 'ppppppp'],
\ ['0000-000', 'ppppppp'],
\ ['0000-000', 'ppppppp']],
\ [['1000-000', 'ppFppFp'],
@@ -469,7 +469,7 @@ func Test_list_locked_var_unlet()
exe "unlockvar " . depth . " l"
endif
let ps = islocked("l").islocked("l[1]").islocked("l[1][1]").islocked("l[1][1][0]").'-'.islocked("l[2]").islocked("l[2]['6']").islocked("l[2]['6'][7]")
- call assert_equal(expected[depth][u][0], ps)
+ call assert_equal(expected[depth][u][0], ps, 'depth: ' .. depth)
let ps = ''
try
unlet l[2]['6'][7]
@@ -673,6 +673,9 @@ func Test_func_arg_list()
call s:arg_list_test(1, 2, [3, 4], {5: 6})
endfunc
+func Test_dict_item_locked()
+endfunc
+
" Tests for reverse(), sort(), uniq()
func Test_reverse_sort_uniq()
let l = ['-0', 'A11', 2, 2, 'xaaa', 4, 'foo', 'foo6', 'foo', [0, 1, 2], 'x8', [0, 1, 2], 1.5]
diff --git a/src/nvim/testdir/test_normal.vim b/src/nvim/testdir/test_normal.vim
index 7c90b444e5..2aaa1ff830 100644
--- a/src/nvim/testdir/test_normal.vim
+++ b/src/nvim/testdir/test_normal.vim
@@ -262,6 +262,7 @@ func Test_formatexpr_scriptlocal_func()
endfunc
set formatexpr=s:Format()
call assert_equal(expand('<SID>') .. 'Format()', &formatexpr)
+ call assert_equal(expand('<SID>') .. 'Format()', &g:formatexpr)
new | only
call setline(1, range(1, 40))
let g:FormatArgs = []
@@ -270,6 +271,7 @@ func Test_formatexpr_scriptlocal_func()
bw!
set formatexpr=<SID>Format()
call assert_equal(expand('<SID>') .. 'Format()', &formatexpr)
+ call assert_equal(expand('<SID>') .. 'Format()', &g:formatexpr)
new | only
call setline(1, range(1, 40))
let g:FormatArgs = []
@@ -277,6 +279,7 @@ func Test_formatexpr_scriptlocal_func()
call assert_equal([4, 2], g:FormatArgs)
bw!
let &formatexpr = 's:Format()'
+ call assert_equal(expand('<SID>') .. 'Format()', &g:formatexpr)
new | only
call setline(1, range(1, 40))
let g:FormatArgs = []
@@ -284,12 +287,55 @@ func Test_formatexpr_scriptlocal_func()
call assert_equal([6, 2], g:FormatArgs)
bw!
let &formatexpr = '<SID>Format()'
+ call assert_equal(expand('<SID>') .. 'Format()', &g:formatexpr)
new | only
call setline(1, range(1, 40))
let g:FormatArgs = []
normal! 8GVjgq
call assert_equal([8, 2], g:FormatArgs)
+ bw!
setlocal formatexpr=
+ setglobal formatexpr=s:Format()
+ call assert_equal(expand('<SID>') .. 'Format()', &g:formatexpr)
+ call assert_equal('', &formatexpr)
+ new
+ call assert_equal(expand('<SID>') .. 'Format()', &formatexpr)
+ call setline(1, range(1, 40))
+ let g:FormatArgs = []
+ normal! 10GVjgq
+ call assert_equal([10, 2], g:FormatArgs)
+ bw!
+ setglobal formatexpr=<SID>Format()
+ call assert_equal(expand('<SID>') .. 'Format()', &g:formatexpr)
+ call assert_equal('', &formatexpr)
+ new
+ call assert_equal(expand('<SID>') .. 'Format()', &formatexpr)
+ call setline(1, range(1, 40))
+ let g:FormatArgs = []
+ normal! 12GVjgq
+ call assert_equal([12, 2], g:FormatArgs)
+ bw!
+ let &g:formatexpr = 's:Format()'
+ call assert_equal(expand('<SID>') .. 'Format()', &g:formatexpr)
+ call assert_equal('', &formatexpr)
+ new
+ call assert_equal(expand('<SID>') .. 'Format()', &formatexpr)
+ call setline(1, range(1, 40))
+ let g:FormatArgs = []
+ normal! 14GVjgq
+ call assert_equal([14, 2], g:FormatArgs)
+ bw!
+ let &g:formatexpr = '<SID>Format()'
+ call assert_equal(expand('<SID>') .. 'Format()', &g:formatexpr)
+ call assert_equal('', &formatexpr)
+ new
+ call assert_equal(expand('<SID>') .. 'Format()', &formatexpr)
+ call setline(1, range(1, 40))
+ let g:FormatArgs = []
+ normal! 16GVjgq
+ call assert_equal([16, 2], g:FormatArgs)
+ bw!
+ set formatexpr=
delfunc s:Format
bw!
endfunc
diff --git a/src/nvim/testdir/test_options.vim b/src/nvim/testdir/test_options.vim
index 11c2977a4e..f51de94bac 100644
--- a/src/nvim/testdir/test_options.vim
+++ b/src/nvim/testdir/test_options.vim
@@ -1238,6 +1238,30 @@ func Test_opt_cdhome()
set cdhome&
endfunc
+func Test_set_completion_2()
+ CheckOption termguicolors
+
+ " Test default option completion
+ set wildoptions=
+ call feedkeys(":set termg\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set termguicolors', @:)
+
+ call feedkeys(":set notermg\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set notermguicolors', @:)
+
+ " Test fuzzy option completion
+ set wildoptions=fuzzy
+ call feedkeys(":set termg\<C-A>\<C-B>\"\<CR>", 'tx')
+ " Nvim doesn't have 'termencoding'
+ " call assert_equal('"set termguicolors termencoding', @:)
+ call assert_equal('"set termguicolors', @:)
+
+ call feedkeys(":set notermg\<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"set notermguicolors', @:)
+
+ set wildoptions=
+endfunc
+
func Test_switchbuf_reset()
set switchbuf=useopen
sblast
diff --git a/src/nvim/testdir/test_packadd.vim b/src/nvim/testdir/test_packadd.vim
index fcb8b8033b..3121b3b4d1 100644
--- a/src/nvim/testdir/test_packadd.vim
+++ b/src/nvim/testdir/test_packadd.vim
@@ -26,7 +26,7 @@ func Test_packadd()
let rtp_entries = split(rtp, ',')
for entry in rtp_entries
- if entry =~? '\<after\>'
+ if entry =~? '\<after\>'
let first_after_entry = entry
break
endif
@@ -186,15 +186,17 @@ func Test_packadd_symlink_dir2()
exec "silent !rmdir" top2_dir
endfunc
-" Check command-line completion for 'packadd'
+" Check command-line completion for :packadd
func Test_packadd_completion()
let optdir1 = &packpath . '/pack/mine/opt'
let optdir2 = &packpath . '/pack/candidate/opt'
call mkdir(optdir1 . '/pluginA', 'p')
call mkdir(optdir1 . '/pluginC', 'p')
+ call writefile([], optdir1 . '/unrelated')
call mkdir(optdir2 . '/pluginB', 'p')
call mkdir(optdir2 . '/pluginC', 'p')
+ call writefile([], optdir2 . '/unrelated')
let li = []
call feedkeys(":packadd \<Tab>')\<C-B>call add(li, '\<CR>", 't')
@@ -260,9 +262,9 @@ func Test_helptags()
helptags ALL
- let tags1 = readfile(docdir1 . '/tags')
+ let tags1 = readfile(docdir1 . '/tags')
call assert_match('look-here', tags1[0])
- let tags2 = readfile(docdir2 . '/tags')
+ let tags2 = readfile(docdir2 . '/tags')
call assert_match('look-away', tags2[0])
call assert_fails('helptags abcxyz', 'E150:')
@@ -358,4 +360,78 @@ func Test_runtime()
call assert_equal('runstartopt', g:sequence)
endfunc
+func Test_runtime_completion()
+ let rundir = &packpath . '/runtime/Aextra'
+ let startdir = &packpath . '/pack/mine/start/foo/Aextra'
+ let optdir = &packpath . '/pack/mine/opt/bar/Aextra'
+ call mkdir(rundir . '/Arunbaz', 'p')
+ call mkdir(startdir . '/Astartbaz', 'p')
+ call mkdir(optdir . '/Aoptbaz', 'p')
+ call writefile([], rundir . '/../Arunfoo.vim')
+ call writefile([], rundir . '/Arunbar.vim')
+ call writefile([], rundir . '/Aunrelated')
+ call writefile([], rundir . '/../Aunrelated')
+ call writefile([], startdir . '/../Astartfoo.vim')
+ call writefile([], startdir . '/Astartbar.vim')
+ call writefile([], startdir . '/Aunrelated')
+ call writefile([], startdir . '/../Aunrelated')
+ call writefile([], optdir . '/../Aoptfoo.vim')
+ call writefile([], optdir . '/Aoptbar.vim')
+ call writefile([], optdir . '/Aunrelated')
+ call writefile([], optdir . '/../Aunrelated')
+ exe 'set rtp=' . &packpath . '/runtime'
+
+ func Check_runtime_completion(arg, arg1, res)
+ call feedkeys(':runtime ' .. a:arg .. "\<C-A>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"runtime ' .. a:arg1 .. join(a:res), @:)
+ call assert_equal(a:res, getcompletion(a:arg, 'runtime'))
+ endfunc
+
+ call Check_runtime_completion('', '',
+ \ ['Aextra/', 'Arunfoo.vim', 'START', 'OPT', 'PACK', 'ALL'])
+ call Check_runtime_completion('S', '',
+ \ ['START'])
+ call Check_runtime_completion('O', '',
+ \ ['OPT'])
+ call Check_runtime_completion('P', '',
+ \ ['PACK'])
+ call Check_runtime_completion('A', '',
+ \ ['Aextra/', 'Arunfoo.vim', 'ALL'])
+ call Check_runtime_completion('Aextra/', '',
+ \ ['Aextra/Arunbar.vim', 'Aextra/Arunbaz/'])
+
+ call Check_runtime_completion('START ', 'START ',
+ \ ['Aextra/', 'Astartfoo.vim'])
+ call Check_runtime_completion('START A', 'START ',
+ \ ['Aextra/', 'Astartfoo.vim'])
+ call Check_runtime_completion('START Aextra/', 'START ',
+ \ ['Aextra/Astartbar.vim', 'Aextra/Astartbaz/'])
+
+ call Check_runtime_completion('OPT ', 'OPT ',
+ \ ['Aextra/', 'Aoptfoo.vim'])
+ call Check_runtime_completion('OPT A', 'OPT ',
+ \ ['Aextra/', 'Aoptfoo.vim'])
+ call Check_runtime_completion('OPT Aextra/', 'OPT ',
+ \ ['Aextra/Aoptbar.vim', 'Aextra/Aoptbaz/'])
+
+ call Check_runtime_completion('PACK ', 'PACK ',
+ \ ['Aextra/', 'Aoptfoo.vim', 'Astartfoo.vim'])
+ call Check_runtime_completion('PACK A', 'PACK ',
+ \ ['Aextra/', 'Aoptfoo.vim', 'Astartfoo.vim'])
+ call Check_runtime_completion('PACK Aextra/', 'PACK ',
+ \ ['Aextra/Aoptbar.vim', 'Aextra/Aoptbaz/',
+ \ 'Aextra/Astartbar.vim', 'Aextra/Astartbaz/'])
+
+ call Check_runtime_completion('ALL ', 'ALL ',
+ \ ['Aextra/', 'Aoptfoo.vim', 'Arunfoo.vim', 'Astartfoo.vim'])
+ call Check_runtime_completion('ALL A', 'ALL ',
+ \ ['Aextra/', 'Aoptfoo.vim', 'Arunfoo.vim', 'Astartfoo.vim'])
+ call Check_runtime_completion('ALL Aextra/', 'ALL ',
+ \ ['Aextra/Aoptbar.vim', 'Aextra/Aoptbaz/',
+ \ 'Aextra/Arunbar.vim', 'Aextra/Arunbaz/',
+ \ 'Aextra/Astartbar.vim', 'Aextra/Astartbaz/'])
+
+ delfunc Check_runtime_completion
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_profile.vim b/src/nvim/testdir/test_profile.vim
index 4225b91bc4..9165f7bace 100644
--- a/src/nvim/testdir/test_profile.vim
+++ b/src/nvim/testdir/test_profile.vim
@@ -403,6 +403,47 @@ func Test_profile_completion()
call feedkeys(":profile start test_prof\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_match('^"profile start.* test_profile\.vim', @:)
+
+ call feedkeys(":profile file test_prof\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_match('"profile file test_profile\.vim', @:)
+ call feedkeys(":profile file test_prof\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_match('"profile file test_profile\.vim', @:)
+ call feedkeys(":profile file test_prof \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_match('"profile file test_prof ', @:)
+ call feedkeys(":profile file X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_match('"profile file X1B2C3', @:)
+
+ func Xprof_test()
+ endfunc
+ call feedkeys(":profile func Xprof\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profile func Xprof_test', @:)
+ call feedkeys(":profile func Xprof\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profile func Xprof_test', @:)
+ call feedkeys(":profile func Xprof \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profile func Xprof ', @:)
+ call feedkeys(":profile func X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profile func X1B2C3', @:)
+
+ call feedkeys(":profdel \<C-A>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profdel file func', @:)
+ call feedkeys(":profdel fu\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profdel func', @:)
+ call feedkeys(":profdel he\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profdel he', @:)
+ call feedkeys(":profdel here \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profdel here ', @:)
+ call feedkeys(":profdel file test_prof\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profdel file test_profile.vim', @:)
+ call feedkeys(":profdel file X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profdel file X1B2C3', @:)
+ call feedkeys(":profdel func Xprof\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profdel func Xprof_test', @:)
+ call feedkeys(":profdel func Xprof_test \<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profdel func Xprof_test ', @:)
+ call feedkeys(":profdel func X1B2C3\<Tab>\<C-B>\"\<CR>", 'tx')
+ call assert_equal('"profdel func X1B2C3', @:)
+
+ delfunc Xprof_test
endfunc
func Test_profile_errors()
diff --git a/src/nvim/testdir/test_search.vim b/src/nvim/testdir/test_search.vim
index a9cad3ed44..885043accf 100644
--- a/src/nvim/testdir/test_search.vim
+++ b/src/nvim/testdir/test_search.vim
@@ -1377,6 +1377,22 @@ func Test_subst_word_under_cursor()
set noincsearch
endfunc
+func Test_search_skip_all_matches()
+ enew
+ call setline(1, ['no match here',
+ \ 'match this line',
+ \ 'nope',
+ \ 'match in this line',
+ \ 'last line',
+ \ ])
+ call cursor(1, 1)
+ let lnum = search('this', '', 0, 0, 'getline(".") =~ "this line"')
+ " Only check that no match is found. Previously it searched forever.
+ call assert_equal(0, lnum)
+
+ bwipe!
+endfunc
+
func Test_search_undefined_behaviour()
CheckFeature terminal
diff --git a/src/nvim/testdir/test_search_stat.vim b/src/nvim/testdir/test_search_stat.vim
index 77bd50ada2..1b2d854829 100644
--- a/src/nvim/testdir/test_search_stat.vim
+++ b/src/nvim/testdir/test_search_stat.vim
@@ -270,6 +270,29 @@ func Test_searchcount_fails()
call assert_fails('echo searchcount({"pos" : [1, 2, []]})', 'E745:')
endfunc
+func Test_search_stat_narrow_screen()
+ " This used to crash Vim
+ let save_columns = &columns
+ try
+ let after =<< trim [CODE]
+ set laststatus=2
+ set columns=16
+ set shortmess-=S showcmd
+ call setline(1, 'abc')
+ call feedkeys("/abc\<CR>:quit!\<CR>")
+ autocmd VimLeavePre * call writefile(["done"], "Xdone")
+ [CODE]
+
+ if !RunVim([], after, '--clean')
+ return
+ endif
+ call assert_equal("done", readfile("Xdone")[0])
+ call delete('Xdone')
+ finally
+ let &columns = save_columns
+ endtry
+endfunc
+
func Test_searchcount_in_statusline()
CheckScreendump
diff --git a/src/nvim/testdir/test_shell.vim b/src/nvim/testdir/test_shell.vim
new file mode 100644
index 0000000000..8b9c7a5b12
--- /dev/null
+++ b/src/nvim/testdir/test_shell.vim
@@ -0,0 +1,209 @@
+" Test for the shell related options ('shell', 'shellcmdflag', 'shellpipe',
+" 'shellquote', 'shellredir', 'shellxescape', and 'shellxquote')
+
+source check.vim
+source shared.vim
+
+func Test_shell_options()
+ " The expected value of 'shellcmdflag', 'shellpipe', 'shellquote',
+ " 'shellredir', 'shellxescape', 'shellxquote' for the supported shells.
+ let shells = []
+ if has('unix')
+ let shells += [['sh', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
+ \ ['ksh', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
+ \ ['mksh', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
+ \ ['zsh', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
+ \ ['zsh-beta', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
+ \ ['bash', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
+ \ ['fish', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
+ \ ['ash', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
+ \ ['dash', '-c', '2>&1| tee', '', '>%s 2>&1', '', ''],
+ \ ['csh', '-c', '|& tee', '', '>&', '', ''],
+ \ ['tcsh', '-c', '|& tee', '', '>&', '', '']]
+ endif
+ if has('win32')
+ let shells += [['cmd', '/s /c', '>%s 2>&1', '', '>%s 2>&1', '', '"']]
+ endif
+
+ " start a new Vim instance with 'shell' set to each of the supported shells
+ " and check the default shell option settings
+ let after =<< trim END
+ let l = [&shell, &shellcmdflag, &shellpipe, &shellquote]
+ let l += [&shellredir, &shellxescape, &shellxquote]
+ call writefile([json_encode(l)], 'Xtestout')
+ qall!
+ END
+ for e in shells
+ if RunVim([], after, '--cmd "set shell=' .. e[0] .. '"')
+ call assert_equal(e, json_decode(readfile('Xtestout')[0]))
+ endif
+ endfor
+
+ " Test shellescape() for each of the shells.
+ for e in shells
+ exe 'set shell=' .. e[0]
+ if e[0] =~# '.*csh$' || e[0] =~# '.*csh.exe$'
+ let str1 = "'cmd \"arg1\" '\\''arg2'\\'' \\!%#'"
+ let str2 = "'cmd \"arg1\" '\\''arg2'\\'' \\\\!\\%\\#'"
+ elseif e[0] =~# '.*powershell$' || e[0] =~# '.*powershell.exe$'
+ let str1 = "'cmd \"arg1\" ''arg2'' !%#'"
+ let str2 = "'cmd \"arg1\" ''arg2'' \\!\\%\\#'"
+ else
+ let str1 = "'cmd \"arg1\" '\\''arg2'\\'' !%#'"
+ let str2 = "'cmd \"arg1\" '\\''arg2'\\'' \\!\\%\\#'"
+ endif
+ call assert_equal(str1, shellescape("cmd \"arg1\" 'arg2' !%#"), e[0])
+ call assert_equal(str2, shellescape("cmd \"arg1\" 'arg2' !%#", 1), e[0])
+
+ " Try running an external command with the shell.
+ if executable(e[0])
+ " set the shell options for the current 'shell'
+ let [&shellcmdflag, &shellpipe, &shellquote, &shellredir,
+ \ &shellxescape, &shellxquote] = e[1:6]
+ new
+ r !echo hello
+ call assert_equal('hello', substitute(getline(2), '\W', '', 'g'), e[0])
+ bwipe!
+ endif
+ endfor
+ set shell& shellcmdflag& shellpipe& shellquote&
+ set shellredir& shellxescape& shellxquote&
+ call delete('Xtestout')
+endfunc
+
+" Test for the 'shell' option
+func Test_shell()
+ throw 'Skipped: Nvim missing :shell currently'
+ CheckUnix
+ let save_shell = &shell
+ set shell=
+ let caught_e91 = 0
+ try
+ shell
+ catch /E91:/
+ let caught_e91 = 1
+ endtry
+ call assert_equal(1, caught_e91)
+ let &shell = save_shell
+endfunc
+
+" Test for the 'shellquote' option
+func Test_shellquote()
+ CheckUnix
+ set shellquote=#
+ set verbose=20
+ redir => v
+ silent! !echo Hello
+ redir END
+ set verbose&
+ set shellquote&
+ call assert_match(': "#echo Hello#"', v)
+endfunc
+
+" Test for the 'shellescape' option
+func Test_shellescape()
+ let save_shell = &shell
+ set shell=bash
+ call assert_equal("'text'", shellescape('text'))
+ call assert_equal("'te\"xt'", 'te"xt'->shellescape())
+ call assert_equal("'te'\\''xt'", shellescape("te'xt"))
+
+ call assert_equal("'te%xt'", shellescape("te%xt"))
+ call assert_equal("'te\\%xt'", shellescape("te%xt", 1))
+ call assert_equal("'te#xt'", shellescape("te#xt"))
+ call assert_equal("'te\\#xt'", shellescape("te#xt", 1))
+ call assert_equal("'te!xt'", shellescape("te!xt"))
+ call assert_equal("'te\\!xt'", shellescape("te!xt", 1))
+
+ call assert_equal("'te\nxt'", shellescape("te\nxt"))
+ call assert_equal("'te\\\nxt'", shellescape("te\nxt", 1))
+ set shell=tcsh
+ call assert_equal("'te\\!xt'", shellescape("te!xt"))
+ call assert_equal("'te\\\\!xt'", shellescape("te!xt", 1))
+ call assert_equal("'te\\\nxt'", shellescape("te\nxt"))
+ call assert_equal("'te\\\\\nxt'", shellescape("te\nxt", 1))
+
+ let &shell = save_shell
+endfunc
+
+" Test for 'shellslash'
+func Test_shellslash()
+ CheckOption shellslash
+ let save_shellslash = &shellslash
+ " The shell and cmdflag, and expected slash in tempname with shellslash set or
+ " unset. The assert checks the file separator before the leafname.
+ " ".*\\\\[^\\\\]*$"
+ let shells = [['cmd', '/c', '/', '/'],
+ \ ['powershell', '-Command', '/', '/'],
+ \ ['sh', '-c', '/', '/']]
+ for e in shells
+ exe 'set shell=' .. e[0] .. ' | set shellcmdflag=' .. e[1]
+ set noshellslash
+ let file = tempname()
+ call assert_match('^.\+' .. e[2] .. '[^' .. e[2] .. ']\+$', file, e[0] .. ' ' .. e[1] .. ' nossl')
+ set shellslash
+ let file = tempname()
+ call assert_match('^.\+' .. e[3] .. '[^' .. e[3] .. ']\+$', file, e[0] .. ' ' .. e[1] .. ' ssl')
+ endfor
+ let &shellslash = save_shellslash
+endfunc
+
+" Test for 'shellxquote'
+func Test_shellxquote()
+ CheckUnix
+
+ let save_shell = &shell
+ let save_sxq = &shellxquote
+ let save_sxe = &shellxescape
+
+ call writefile(['#!/bin/sh', 'echo "Cmd: [$*]" > Xlog'], 'Xtestshell')
+ call setfperm('Xtestshell', "r-x------")
+ set shell=./Xtestshell
+
+ set shellxquote=\\"
+ call feedkeys(":!pwd\<CR>\<CR>", 'xt')
+ call assert_equal(['Cmd: [-c "pwd"]'], readfile('Xlog'))
+
+ set shellxquote=(
+ call feedkeys(":!pwd\<CR>\<CR>", 'xt')
+ call assert_equal(['Cmd: [-c (pwd)]'], readfile('Xlog'))
+
+ set shellxquote=\\"(
+ call feedkeys(":!pwd\<CR>\<CR>", 'xt')
+ call assert_equal(['Cmd: [-c "(pwd)"]'], readfile('Xlog'))
+
+ set shellxescape=\"&<<()@^
+ set shellxquote=(
+ call feedkeys(":!pwd\"&<<{}@^\<CR>\<CR>", 'xt')
+ call assert_equal(['Cmd: [-c (pwd^"^&^<^<{}^@^^)]'], readfile('Xlog'))
+
+ let &shell = save_shell
+ let &shellxquote = save_sxq
+ let &shellxescape = save_sxe
+ call delete('Xtestshell')
+ call delete('Xlog')
+endfunc
+
+" Test for using the shell set in the $SHELL environment variable
+func Test_set_shell()
+ let after =<< trim [CODE]
+ call writefile([&shell], "Xtestout")
+ quit!
+ [CODE]
+
+ if has('win32')
+ let $SHELL = 'C:\with space\cmd.exe'
+ let expected = '"C:\with space\cmd.exe"'
+ else
+ let $SHELL = '/bin/with space/sh'
+ let expected = '"/bin/with space/sh"'
+ endif
+
+ if RunVimPiped([], after, '', '')
+ let lines = readfile('Xtestout')
+ call assert_equal(expected, lines[0])
+ endif
+ call delete('Xtestout')
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_spell.vim b/src/nvim/testdir/test_spell.vim
index a919156066..c840e834b9 100644
--- a/src/nvim/testdir/test_spell.vim
+++ b/src/nvim/testdir/test_spell.vim
@@ -531,8 +531,23 @@ func Test_spellsuggest_timeout()
call assert_fails('set spellsuggest=timeout:--9', 'E474:')
endfunc
+func Test_spellsuggest_visual_end_of_line()
+ let enc_save = &encoding
+ " set encoding=iso8859
+
+ " This was reading beyond the end of the line.
+ norm R00000000000
+ sil norm 0
+ sil! norm i00000)
+ sil! norm i00000)
+ call feedkeys("\<CR>")
+ norm z=
+
+ let &encoding = enc_save
+endfunc
+
func Test_spellinfo()
- throw 'skipped: Nvim does not support enc=latin1'
+ throw 'Skipped: Nvim does not support enc=latin1'
new
let runtime = substitute($VIMRUNTIME, '\\', '/', 'g')
diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim
index 54b7636f69..1ee1d0dfe3 100644
--- a/src/nvim/testdir/test_startup.vim
+++ b/src/nvim/testdir/test_startup.vim
@@ -725,27 +725,6 @@ func Test_read_stdin()
call delete('Xtestout')
endfunc
-func Test_set_shell()
- let after =<< trim [CODE]
- call writefile([&shell], "Xtestout")
- quit!
- [CODE]
-
- if has('win32')
- let $SHELL = 'C:\with space\cmd.exe'
- let expected = '"C:\with space\cmd.exe"'
- else
- let $SHELL = '/bin/with space/sh'
- let expected = '"/bin/with space/sh"'
- endif
-
- if RunVimPiped([], after, '', '')
- let lines = readfile('Xtestout')
- call assert_equal(expected, lines[0])
- endif
- call delete('Xtestout')
-endfunc
-
func Test_progpath()
" Tests normally run with "./vim" or "../vim", these must have been expanded
" to a full path.
@@ -1064,7 +1043,7 @@ func Test_io_not_a_terminal()
\ 'Vim: Warning: Input is not from a terminal'], l)
endfunc
-" Test for --not-a-term avoiding escape codes.
+" Test for not being a term avoiding escape codes.
func Test_not_a_term()
CheckUnix
CheckNotGui
@@ -1075,18 +1054,14 @@ func Test_not_a_term()
let redir = &shellredir .. ' Xvimout'
endif
- " Without --not-a-term there are a few escape sequences.
- " This will take 2 seconds because of the missing --not-a-term
+ " As nvim checks the environment by itself there will be no escape sequences
+ " This will also happen to take two (2) seconds.
let cmd = GetVimProg() .. ' --cmd quit ' .. redir
exe "silent !" . cmd
- call assert_match("\<Esc>", readfile('Xvimout')->join())
+ call assert_notmatch("\e", readfile('Xvimout')->join())
call delete('Xvimout')
- " With --not-a-term there are no escape sequences.
- let cmd = GetVimProg() .. ' --not-a-term --cmd quit ' .. redir
- exe "silent !" . cmd
- call assert_notmatch("\<Esc>", readfile('Xvimout')->join())
- call delete('Xvimout')
+ " --not-a-term flag has thus been deleted
endfunc
diff --git a/src/nvim/testdir/test_substitute.vim b/src/nvim/testdir/test_substitute.vim
index 5fd30c7da7..c99a0d456d 100644
--- a/src/nvim/testdir/test_substitute.vim
+++ b/src/nvim/testdir/test_substitute.vim
@@ -1076,6 +1076,19 @@ func Test_sub_open_cmdline_win()
call delete('Xresult')
endfunc
+" This was editing a script file from the expression
+func Test_sub_edit_scriptfile()
+ new
+ norm o0000000000000000000000000000000000000000000000000000
+ func EditScript()
+ silent! scr! Xfile
+ endfunc
+ s/\%')/\=EditScript()
+
+ delfunc EditScript
+ bwipe!
+endfunc
+
" Test for the 2-letter and 3-letter :substitute commands
func Test_substitute_short_cmd()
new
diff --git a/src/nvim/testdir/test_system.vim b/src/nvim/testdir/test_system.vim
index bfa8a277bd..6c8373b335 100644
--- a/src/nvim/testdir/test_system.vim
+++ b/src/nvim/testdir/test_system.vim
@@ -142,40 +142,4 @@ func Test_system_with_shell_quote()
endtry
endfunc
-" Test for 'shellxquote'
-func Test_Shellxquote()
- CheckUnix
-
- let save_shell = &shell
- let save_sxq = &shellxquote
- let save_sxe = &shellxescape
-
- call writefile(['#!/bin/sh', 'echo "Cmd: [$*]" > Xlog'], 'Xtestshell')
- call setfperm('Xtestshell', "r-x------")
- set shell=./Xtestshell
-
- set shellxquote=\\"
- call feedkeys(":!pwd\<CR>\<CR>", 'xt')
- call assert_equal(['Cmd: [-c "pwd"]'], readfile('Xlog'))
-
- set shellxquote=(
- call feedkeys(":!pwd\<CR>\<CR>", 'xt')
- call assert_equal(['Cmd: [-c (pwd)]'], readfile('Xlog'))
-
- set shellxquote=\\"(
- call feedkeys(":!pwd\<CR>\<CR>", 'xt')
- call assert_equal(['Cmd: [-c "(pwd)"]'], readfile('Xlog'))
-
- set shellxescape=\"&<<()@^
- set shellxquote=(
- call feedkeys(":!pwd\"&<<{}@^\<CR>\<CR>", 'xt')
- call assert_equal(['Cmd: [-c (pwd^"^&^<^<{}^@^^)]'], readfile('Xlog'))
-
- let &shell = save_shell
- let &shellxquote = save_sxq
- let &shellxescape = save_sxe
- call delete('Xtestshell')
- call delete('Xlog')
-endfunc
-
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_taglist.vim b/src/nvim/testdir/test_taglist.vim
index 0387ef2bd8..75d28c3ec4 100644
--- a/src/nvim/testdir/test_taglist.vim
+++ b/src/nvim/testdir/test_taglist.vim
@@ -105,8 +105,8 @@ func Test_tagfiles()
help
let tf = tagfiles()
" Nvim: expectation(s) based on tags in build dir (added to &rtp).
- " Filter out the (non-existing) '../../../runtime/doc/tags'.
- call filter(tf, 'filereadable(v:val)')
+ " Filter out the '../../../runtime/doc/tags'.
+ call filter(tf, 'v:val != "../../../runtime/doc/tags"')
call assert_equal(1, len(tf))
call assert_equal(fnamemodify(expand('$BUILD_DIR/runtime/doc/tags'), ':p:gs?\\?/?'),
\ fnamemodify(tf[0], ':p:gs?\\?/?'))
diff --git a/src/nvim/testdir/test_utf8.vim b/src/nvim/testdir/test_utf8.vim
index 9146cf7ab3..e5f6d68720 100644
--- a/src/nvim/testdir/test_utf8.vim
+++ b/src/nvim/testdir/test_utf8.vim
@@ -167,6 +167,39 @@ func Test_setcellwidths()
call assert_equal(2, strwidth("\u1339"))
call assert_equal(1, strwidth("\u133a"))
+ for aw in ['single', 'double']
+ exe 'set ambiwidth=' . aw
+ " Handle \u0080 to \u009F as control chars even on MS-Windows.
+ set isprint=@,161-255
+
+ call setcellwidths([])
+ " Control chars
+ call assert_equal(4, strwidth("\u0081"))
+ call assert_equal(6, strwidth("\uFEFF"))
+ " Ambiguous width chars
+ call assert_equal((aw == 'single') ? 1 : 2, strwidth("\u00A1"))
+ call assert_equal((aw == 'single') ? 1 : 2, strwidth("\u2010"))
+
+ call setcellwidths([[0x81, 0x81, 1], [0xA1, 0xA1, 1],
+ \ [0x2010, 0x2010, 1], [0xFEFF, 0xFEFF, 1]])
+ " Control chars
+ call assert_equal(4, strwidth("\u0081"))
+ call assert_equal(6, strwidth("\uFEFF"))
+ " Ambiguous width chars
+ call assert_equal(1, strwidth("\u00A1"))
+ call assert_equal(1, strwidth("\u2010"))
+
+ call setcellwidths([[0x81, 0x81, 2], [0xA1, 0xA1, 2],
+ \ [0x2010, 0x2010, 2], [0xFEFF, 0xFEFF, 2]])
+ " Control chars
+ call assert_equal(4, strwidth("\u0081"))
+ call assert_equal(6, strwidth("\uFEFF"))
+ " Ambiguous width chars
+ call assert_equal(2, strwidth("\u00A1"))
+ call assert_equal(2, strwidth("\u2010"))
+ endfor
+ set ambiwidth& isprint&
+
call setcellwidths([])
call assert_fails('call setcellwidths(1)', 'E714:')
@@ -199,6 +232,26 @@ func Test_setcellwidths()
call setcellwidths([])
endfunc
+func Test_getcellwidths()
+ call setcellwidths([])
+ call assert_equal([], getcellwidths())
+
+ let widthlist = [
+ \ [0x1330, 0x1330, 2],
+ \ [9999, 10000, 1],
+ \ [0x1337, 0x1339, 2],
+ \]
+ let widthlistsorted = [
+ \ [0x1330, 0x1330, 2],
+ \ [0x1337, 0x1339, 2],
+ \ [9999, 10000, 1],
+ \]
+ call setcellwidths(widthlist)
+ call assert_equal(widthlistsorted, getcellwidths())
+
+ call setcellwidths([])
+endfunc
+
func Test_setcellwidths_dump()
CheckRunVimInTerminal
diff --git a/src/nvim/testdir/test_virtualedit.vim b/src/nvim/testdir/test_virtualedit.vim
index 2bf8c3fc77..20a5f87517 100644
--- a/src/nvim/testdir/test_virtualedit.vim
+++ b/src/nvim/testdir/test_virtualedit.vim
@@ -537,6 +537,19 @@ func Test_global_local_virtualedit()
set virtualedit&
endfunc
+func Test_virtualedit_setlocal()
+ enew
+ setglobal virtualedit=all
+ setlocal virtualedit=all
+ normal! l
+ redraw
+ setlocal virtualedit=none
+ call assert_equal(1, wincol())
+
+ setlocal virtualedit&
+ set virtualedit&
+endfunc
+
func Test_virtualedit_mouse()
let save_mouse = &mouse
set mouse=a
diff --git a/src/nvim/testdir/test_visual.vim b/src/nvim/testdir/test_visual.vim
index 14d62089cf..1e9629c2c4 100644
--- a/src/nvim/testdir/test_visual.vim
+++ b/src/nvim/testdir/test_visual.vim
@@ -1319,6 +1319,17 @@ func Test_visual_block_with_substitute()
endfunc
func Test_visual_reselect_with_count()
+ enew
+ call setline(1, ['aaaaaa', '✗ bbbb', '✗ bbbb'])
+ exe "normal! 2Gw\<C-V>jed"
+ exe "normal! gg0lP"
+ call assert_equal(['abbbbaaaaa', '✗bbbb ', '✗ '], getline(1, '$'))
+
+ exe "normal! 1vr."
+ call assert_equal(['a....aaaaa', '✗.... ', '✗ '], getline(1, '$'))
+
+ bwipe!
+
" this was causing an illegal memory access
let lines =<< trim END
diff --git a/src/nvim/testdir/test_writefile.vim b/src/nvim/testdir/test_writefile.vim
index 6d27407f82..6019cee193 100644
--- a/src/nvim/testdir/test_writefile.vim
+++ b/src/nvim/testdir/test_writefile.vim
@@ -896,6 +896,9 @@ endfunc
" link to the original file. The backup file should not be modified.
func Test_write_backup_symlink()
CheckUnix
+ call mkdir('Xbackup')
+ let save_backupdir = &backupdir
+ set backupdir=.,./Xbackup
call writefile(['1111'], 'Xfile')
silent !ln -s Xfile Xfile.bak
@@ -904,11 +907,18 @@ func Test_write_backup_symlink()
write
call assert_equal('link', getftype('Xfile.bak'))
call assert_equal('Xfile', resolve('Xfile.bak'))
+ " backup file should be created in the 'backup' directory
+ if !has('bsd')
+ " This check fails on FreeBSD
+ call assert_true(filereadable('./Xbackup/Xfile.bak'))
+ endif
set backup& backupcopy& backupext&
- close
+ %bw
call delete('Xfile')
call delete('Xfile.bak')
+ call delete('Xbackup', 'rf')
+ let &backupdir = save_backupdir
endfunc
" Test for ':write ++bin' and ':write ++nobin'
diff --git a/src/nvim/testing.c b/src/nvim/testing.c
index edb24c6dc5..b5921b3445 100644
--- a/src/nvim/testing.c
+++ b/src/nvim/testing.c
@@ -68,61 +68,62 @@ static void prepare_assert_error(garray_T *gap)
/// Append "p[clen]" to "gap", escaping unprintable characters.
/// Changes NL to \n, CR to \r, etc.
-static void ga_concat_esc(garray_T *gap, const char_u *p, int clen)
+static void ga_concat_esc(garray_T *gap, const char *p, int clen)
FUNC_ATTR_NONNULL_ALL
{
- char_u buf[NUMBUFLEN];
+ char buf[NUMBUFLEN];
if (clen > 1) {
memmove(buf, p, (size_t)clen);
buf[clen] = NUL;
- ga_concat(gap, (char *)buf);
- } else {
- switch (*p) {
- case BS:
- ga_concat(gap, "\\b"); break;
- case ESC:
- ga_concat(gap, "\\e"); break;
- case FF:
- ga_concat(gap, "\\f"); break;
- case NL:
- ga_concat(gap, "\\n"); break;
- case TAB:
- ga_concat(gap, "\\t"); break;
- case CAR:
- ga_concat(gap, "\\r"); break;
- case '\\':
- ga_concat(gap, "\\\\"); break;
- default:
- if (*p < ' ' || *p == 0x7f) {
- vim_snprintf((char *)buf, NUMBUFLEN, "\\x%02x", *p);
- ga_concat(gap, (char *)buf);
- } else {
- ga_append(gap, (char)(*p));
- }
- break;
+ ga_concat(gap, buf);
+ return;
+ }
+
+ switch (*p) {
+ case BS:
+ ga_concat(gap, "\\b"); break;
+ case ESC:
+ ga_concat(gap, "\\e"); break;
+ case FF:
+ ga_concat(gap, "\\f"); break;
+ case NL:
+ ga_concat(gap, "\\n"); break;
+ case TAB:
+ ga_concat(gap, "\\t"); break;
+ case CAR:
+ ga_concat(gap, "\\r"); break;
+ case '\\':
+ ga_concat(gap, "\\\\"); break;
+ default:
+ if ((uint8_t)(*p) < ' ' || *p == 0x7f) {
+ vim_snprintf(buf, NUMBUFLEN, "\\x%02x", *p);
+ ga_concat(gap, buf);
+ } else {
+ ga_append(gap, (uint8_t)(*p));
}
+ break;
}
}
/// Append "str" to "gap", escaping unprintable characters.
/// Changes NL to \n, CR to \r, etc.
-static void ga_concat_shorten_esc(garray_T *gap, const char_u *str)
+static void ga_concat_shorten_esc(garray_T *gap, const char *str)
FUNC_ATTR_NONNULL_ARG(1)
{
- char_u buf[NUMBUFLEN];
+ char buf[NUMBUFLEN];
if (str == NULL) {
ga_concat(gap, "NULL");
return;
}
- for (const char_u *p = str; *p != NUL; p++) {
+ for (const char *p = str; *p != NUL; p++) {
int same_len = 1;
- const char_u *s = p;
+ const char *s = p;
const int c = mb_ptr2char_adv(&s);
const int clen = (int)(s - p);
- while (*s != NUL && c == utf_ptr2char((char *)s)) {
+ while (*s != NUL && c == utf_ptr2char(s)) {
same_len++;
s += clen;
}
@@ -130,8 +131,8 @@ static void ga_concat_shorten_esc(garray_T *gap, const char_u *str)
ga_concat(gap, "\\[");
ga_concat_esc(gap, p, clen);
ga_concat(gap, " occurs ");
- vim_snprintf((char *)buf, NUMBUFLEN, "%d", same_len);
- ga_concat(gap, (char *)buf);
+ vim_snprintf(buf, NUMBUFLEN, "%d", same_len);
+ ga_concat(gap, buf);
ga_concat(gap, " times]");
p = s - 1;
} else {
@@ -141,10 +142,10 @@ static void ga_concat_shorten_esc(garray_T *gap, const char_u *str)
}
/// Fill "gap" with information about an assert error.
-static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_str,
+static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char *exp_str,
typval_T *exp_tv_arg, typval_T *got_tv_arg, assert_type_T atype)
{
- char_u *tofree;
+ char *tofree;
typval_T *exp_tv = exp_tv_arg;
typval_T *got_tv = got_tv_arg;
bool did_copy = false;
@@ -154,8 +155,8 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_s
&& !(opt_msg_tv->v_type == VAR_STRING
&& (opt_msg_tv->vval.v_string == NULL
|| *opt_msg_tv->vval.v_string == NUL))) {
- tofree = (char_u *)encode_tv2echo(opt_msg_tv, NULL);
- ga_concat(gap, (char *)tofree);
+ tofree = encode_tv2echo(opt_msg_tv, NULL);
+ ga_concat(gap, tofree);
xfree(tofree);
ga_concat(gap, ": ");
}
@@ -218,7 +219,7 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_s
}
}
- tofree = (char_u *)encode_tv2string(exp_tv, NULL);
+ tofree = encode_tv2string(exp_tv, NULL);
ga_concat_shorten_esc(gap, tofree);
xfree(tofree);
} else {
@@ -233,7 +234,7 @@ static void fill_assert_error(garray_T *gap, typval_T *opt_msg_tv, char_u *exp_s
} else {
ga_concat(gap, " but got ");
}
- tofree = (char_u *)encode_tv2string(got_tv, NULL);
+ tofree = encode_tv2string(got_tv, NULL);
ga_concat_shorten_esc(gap, tofree);
xfree(tofree);
@@ -306,7 +307,7 @@ static int assert_bool(typval_T *argvars, bool is_true)
: kBoolVarFalse)))) {
prepare_assert_error(&ga);
fill_assert_error(&ga, &argvars[1],
- (char_u *)(is_true ? "True" : "False"),
+ is_true ? "True" : "False",
NULL, &argvars[0], ASSERT_OTHER);
assert_error(&ga);
ga_clear(&ga);
@@ -642,8 +643,8 @@ static int assert_inrange(typval_T *argvars)
garray_T ga;
prepare_assert_error(&ga);
if (argvars[3].v_type != VAR_UNKNOWN) {
- char_u *const tofree = (char_u *)encode_tv2string(&argvars[3], NULL);
- ga_concat(&ga, (char *)tofree);
+ char *const tofree = encode_tv2string(&argvars[3], NULL);
+ ga_concat(&ga, tofree);
xfree(tofree);
} else {
char msg[80];
@@ -671,7 +672,7 @@ static int assert_inrange(typval_T *argvars)
vim_snprintf(msg, sizeof(msg),
"range %" PRIdVARNUMBER " - %" PRIdVARNUMBER ",",
lower, upper); // -V576
- fill_assert_error(&ga, &argvars[3], (char_u *)msg, NULL, &argvars[2],
+ fill_assert_error(&ga, &argvars[3], msg, NULL, &argvars[2],
ASSERT_INRANGE);
assert_error(&ga);
ga_clear(&ga);
diff --git a/src/nvim/textformat.c b/src/nvim/textformat.c
index 4af629d091..e30580a748 100644
--- a/src/nvim/textformat.c
+++ b/src/nvim/textformat.c
@@ -127,13 +127,13 @@ void internal_format(int textwidth, int second_indent, int flags, bool format_on
// Don't break until after the comment leader
if (do_comments) {
- char_u *line = (char_u *)get_cursor_line_ptr();
- leader_len = get_leader_len((char *)line, NULL, false, true);
+ char *line = get_cursor_line_ptr();
+ leader_len = get_leader_len(line, NULL, false, true);
if (leader_len == 0 && curbuf->b_p_cin) {
// Check for a line comment after code.
- int comment_start = check_linecomment((char *)line);
+ int comment_start = check_linecomment(line);
if (comment_start != MAXCOL) {
- leader_len = get_leader_len((char *)line + comment_start, NULL, false, true);
+ leader_len = get_leader_len(line + comment_start, NULL, false, true);
if (leader_len != 0) {
leader_len += comment_start;
}
@@ -477,25 +477,25 @@ void internal_format(int textwidth, int second_indent, int flags, bool format_on
/// comment leader changes.
static int fmt_check_par(linenr_T lnum, int *leader_len, char **leader_flags, bool do_comments)
{
- char_u *flags = NULL; // init for GCC
- char_u *ptr;
+ char *flags = NULL; // init for GCC
+ char *ptr;
- ptr = (char_u *)ml_get(lnum);
+ ptr = ml_get(lnum);
if (do_comments) {
- *leader_len = get_leader_len((char *)ptr, leader_flags, false, true);
+ *leader_len = get_leader_len(ptr, leader_flags, false, true);
} else {
*leader_len = 0;
}
if (*leader_len > 0) {
// Search for 'e' flag in comment leader flags.
- flags = (char_u *)(*leader_flags);
+ flags = *leader_flags;
while (*flags && *flags != ':' && *flags != COM_END) {
flags++;
}
}
- return *skipwhite((char *)ptr + *leader_len) == NUL
+ return *skipwhite(ptr + *leader_len) == NUL
|| (*leader_len > 0 && *flags == COM_END)
|| startPS(lnum, NUL, false);
}
@@ -544,7 +544,8 @@ static bool same_leader(linenr_T lnum, int leader1_len, char *leader1_flags, int
return false;
}
if (*p == COM_START) {
- if (*(ml_get(lnum) + leader1_len) == NUL) {
+ int line_len = (int)strlen(ml_get(lnum));
+ if (line_len <= leader1_len) {
return false;
}
if (leader2_flags == NULL || leader2_len == 0) {
@@ -587,7 +588,7 @@ static bool same_leader(linenr_T lnum, int leader1_len, char *leader1_flags, int
/// false when the previous line is in the same paragraph.
static bool paragraph_start(linenr_T lnum)
{
- char_u *p;
+ char *p;
int leader_len = 0; // leader len of current line
char *leader_flags = NULL; // flags for leader of current line
int next_leader_len = 0; // leader len of next line
@@ -596,7 +597,7 @@ static bool paragraph_start(linenr_T lnum)
if (lnum <= 1) {
return true; // start of the file
}
- p = (char_u *)ml_get(lnum - 1);
+ p = ml_get(lnum - 1);
if (*p == NUL) {
return true; // after empty line
}
@@ -735,22 +736,24 @@ void check_auto_format(bool end_insert)
int c = ' ';
int cc;
- if (did_add_space) {
- cc = gchar_cursor();
- if (!WHITECHAR(cc)) {
- // Somehow the space was removed already.
+ if (!did_add_space) {
+ return;
+ }
+
+ cc = gchar_cursor();
+ if (!WHITECHAR(cc)) {
+ // Somehow the space was removed already.
+ did_add_space = false;
+ } else {
+ if (!end_insert) {
+ inc_cursor();
+ c = gchar_cursor();
+ dec_cursor();
+ }
+ if (c != NUL) {
+ // The space is no longer at the end of the line, delete it.
+ del_char(false);
did_add_space = false;
- } else {
- if (!end_insert) {
- inc_cursor();
- c = gchar_cursor();
- dec_cursor();
- }
- if (c != NUL) {
- // The space is no longer at the end of the line, delete it.
- del_char(false);
- did_add_space = false;
- }
}
}
}
diff --git a/src/nvim/textobject.c b/src/nvim/textobject.c
index ee6c39a8ba..8e786c271c 100644
--- a/src/nvim/textobject.c
+++ b/src/nvim/textobject.c
@@ -4,6 +4,7 @@
// textobject.c: functions for text objects
#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
#include <string.h>
@@ -28,7 +29,6 @@
#include "nvim/search.h"
#include "nvim/strings.h"
#include "nvim/textobject.h"
-#include "nvim/types.h"
#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -273,7 +273,7 @@ bool startPS(linenr_T lnum, int para, bool both)
return true;
}
if (*s == '.' && (inmacro(p_sections, s + 1)
- || (!para && inmacro((char *)p_para, s + 1)))) {
+ || (!para && inmacro(p_para, s + 1)))) {
return true;
}
return false;
@@ -1078,7 +1078,7 @@ static bool in_html_tag(bool end_tag)
if (inc(&pos) < 0) {
return false;
}
- c = *ml_get_pos(&pos);
+ c = (uint8_t)(*ml_get_pos(&pos));
if (c == '>') {
break;
}
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index b837a380d5..733aa25f03 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -8,31 +8,27 @@
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
-#include "nvim/api/vim.h"
#include "nvim/ascii.h"
-#include "nvim/autocmd.h"
#include "nvim/charset.h"
#include "nvim/event/defs.h"
-#include "nvim/event/multiqueue.h"
-#include "nvim/globals.h"
#include "nvim/log.h"
#include "nvim/macros.h"
#include "nvim/main.h"
#include "nvim/map.h"
#include "nvim/memory.h"
-#include "nvim/message.h"
#include "nvim/option.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
#include "nvim/tui/input.h"
#include "nvim/tui/input_defs.h"
#include "nvim/tui/tui.h"
+#include "nvim/types.h"
+#include "nvim/ui_client.h"
#ifdef MSWIN
# include "nvim/os/os_win_console.h"
#endif
#include "nvim/event/rstream.h"
#include "nvim/msgpack_rpc/channel.h"
-#include "nvim/ui.h"
#define KEY_BUFFER_SIZE 0xfff
@@ -121,14 +117,6 @@ static const struct kitty_key_map_entry {
static Map(KittyKey, cstr_t) kitty_key_map = MAP_INIT;
-#ifndef UNIT_TESTING
-typedef enum {
- kIncomplete = -1,
- kNotApplicable = 0,
- kComplete = 1,
-} HandleState;
-#endif
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "tui/input.c.generated.h"
#endif
@@ -153,19 +141,7 @@ void tinput_init(TermInput *input, Loop *loop)
kitty_key_map_entry[i].name);
}
- // If stdin is not a pty, switch to stderr. For cases like:
- // echo q | nvim -es
- // ls *.md | xargs nvim
-#ifdef MSWIN
- if (!os_isatty(input->in_fd)) {
- input->in_fd = os_get_conin_fd();
- }
-#else
- if (!os_isatty(input->in_fd) && os_isatty(STDERR_FILENO)) {
- input->in_fd = STDERR_FILENO;
- }
-#endif
- input_global_fd_init(input->in_fd);
+ input->in_fd = STDIN_FILENO;
const char *term = os_getenv("TERM");
if (!term) {
@@ -174,7 +150,7 @@ void tinput_init(TermInput *input, Loop *loop)
input->tk = termkey_new_abstract(term,
TERMKEY_FLAG_UTF8 | TERMKEY_FLAG_NOSTART);
- termkey_hook_terminfo_getstr(input->tk, input->tk_ti_hook_fn, NULL);
+ termkey_hook_terminfo_getstr(input->tk, input->tk_ti_hook_fn, input);
termkey_start(input->tk);
int curflags = termkey_get_canonflags(input->tk);
@@ -600,7 +576,7 @@ static void set_bg(char *bgvalue)
// ignored in the calculations.
//
// [1] https://en.wikipedia.org/wiki/Luma_%28video%29
-static HandleState handle_background_color(TermInput *input)
+HandleState handle_background_color(TermInput *input)
{
if (input->waiting_for_bg_response <= 0) {
return kNotApplicable;
@@ -671,7 +647,7 @@ static HandleState handle_background_color(TermInput *input)
bool is_dark = luminance < 0.5;
char *bgvalue = is_dark ? "dark" : "light";
DLOG("bg response: %s", bgvalue);
- ui_client_bg_respose = is_dark ? kTrue : kFalse;
+ ui_client_bg_response = is_dark ? kTrue : kFalse;
set_bg(bgvalue);
input->waiting_for_bg_response = 0;
} else if (!done && !bad) {
@@ -685,12 +661,6 @@ static HandleState handle_background_color(TermInput *input)
}
return kComplete;
}
-#ifdef UNIT_TESTING
-HandleState ut_handle_background_color(TermInput *input)
-{
- return handle_background_color(input);
-}
-#endif
static void handle_raw_buffer(TermInput *input, bool force)
{
diff --git a/src/nvim/tui/input.h b/src/nvim/tui/input.h
index 5df108b107..d33cea6383 100644
--- a/src/nvim/tui/input.h
+++ b/src/nvim/tui/input.h
@@ -40,18 +40,14 @@ typedef struct term_input {
TUIData *tui_data;
} TermInput;
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "tui/input.h.generated.h"
-#endif
-
-#ifdef UNIT_TESTING
typedef enum {
kIncomplete = -1,
kNotApplicable = 0,
kComplete = 1,
} HandleState;
-HandleState ut_handle_background_color(TermInput *input);
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "tui/input.h.generated.h"
#endif
#endif // NVIM_TUI_INPUT_H
diff --git a/src/nvim/tui/terminfo.c b/src/nvim/tui/terminfo.c
index 507e9df21e..d630a34ce2 100644
--- a/src/nvim/tui/terminfo.c
+++ b/src/nvim/tui/terminfo.c
@@ -7,12 +7,12 @@
#include <string.h>
#include <unibilium.h>
+#include "klib/kvec.h"
+#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
+#include "nvim/ascii.h"
#include "nvim/charset.h"
-#include "nvim/globals.h"
#include "nvim/memory.h"
-#include "nvim/message.h"
-#include "nvim/option.h"
#include "nvim/strings.h"
#include "nvim/tui/terminfo.h"
#include "nvim/tui/terminfo_defs.h"
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 44f6718039..ceda3b2076 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -16,7 +16,6 @@
#include "klib/kvec.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
-#include "nvim/api/vim.h"
#include "nvim/ascii.h"
#include "nvim/cursor_shape.h"
#include "nvim/event/defs.h"
@@ -32,12 +31,10 @@
#include "nvim/main.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
-#include "nvim/message.h"
#include "nvim/msgpack_rpc/channel.h"
-#include "nvim/option.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
-#include "nvim/os/signal.h"
+#include "nvim/ui_client.h"
#ifdef MSWIN
# include "nvim/os/os_win_console.h"
#endif
@@ -46,7 +43,6 @@
#include "nvim/tui/tui.h"
#include "nvim/ugrid.h"
#include "nvim/ui.h"
-#include "nvim/vim.h"
// Space reserved in two output buffers to make the cursor normal or invisible
// when flushing. No existing terminal will require 32 bytes to do that.
@@ -141,6 +137,7 @@ struct TUIData {
int enable_bracketed_paste, disable_bracketed_paste;
int enable_lr_margin, disable_lr_margin;
int enter_strikethrough_mode;
+ int enter_altfont_mode;
int set_rgb_foreground, set_rgb_background;
int set_cursor_color;
int reset_cursor_color;
@@ -255,6 +252,7 @@ static void terminfo_start(TUIData *tui)
tui->unibi_ext.enable_bracketed_paste = -1;
tui->unibi_ext.disable_bracketed_paste = -1;
tui->unibi_ext.enter_strikethrough_mode = -1;
+ tui->unibi_ext.enter_altfont_mode = -1;
tui->unibi_ext.enable_lr_margin = -1;
tui->unibi_ext.disable_lr_margin = -1;
tui->unibi_ext.enable_focus_reporting = -1;
@@ -460,7 +458,11 @@ static void tui_terminal_stop(TUIData *tui)
void tui_stop(TUIData *tui)
{
+ if (tui->stopped) {
+ return;
+ }
tui_terminal_stop(tui);
+ stream_set_blocking(tui->input.in_fd, true); // normalize stream (#2598)
tinput_destroy(&tui->input);
tui->stopped = true;
signal_watcher_close(&tui->winch_handle, NULL);
@@ -515,7 +517,7 @@ static bool attrs_differ(TUIData *tui, int id1, int id2, bool rgb)
return a1.cterm_fg_color != a2.cterm_fg_color
|| a1.cterm_bg_color != a2.cterm_bg_color
|| a1.cterm_ae_attr != a2.cterm_ae_attr
- || (a1.cterm_ae_attr & HL_ANY_UNDERLINE
+ || (a1.cterm_ae_attr & HL_UNDERLINE_MASK
&& a1.rgb_sp_color != a2.rgb_sp_color);
}
}
@@ -535,6 +537,7 @@ static void update_attrs(TUIData *tui, int attr_id)
bool reverse = attr & HL_INVERSE;
bool standout = attr & HL_STANDOUT;
bool strikethrough = attr & HL_STRIKETHROUGH;
+ bool altfont = attr & HL_ALTFONT;
bool underline;
bool undercurl;
@@ -542,13 +545,14 @@ static void update_attrs(TUIData *tui, int attr_id)
bool underdotted;
bool underdashed;
if (tui->unibi_ext.set_underline_style != -1) {
- underline = attr & HL_UNDERLINE;
- undercurl = attr & HL_UNDERCURL;
- underdouble = attr & HL_UNDERDOUBLE;
- underdashed = attr & HL_UNDERDASHED;
- underdotted = attr & HL_UNDERDOTTED;
+ int ul = attr & HL_UNDERLINE_MASK;
+ underline = ul == HL_UNDERLINE;
+ undercurl = ul == HL_UNDERCURL;
+ underdouble = ul == HL_UNDERDOUBLE;
+ underdashed = ul == HL_UNDERDASHED;
+ underdotted = ul == HL_UNDERDOTTED;
} else {
- underline = attr & HL_ANY_UNDERLINE;
+ underline = attr & HL_UNDERLINE_MASK;
undercurl = false;
underdouble = false;
underdotted = false;
@@ -593,6 +597,9 @@ static void update_attrs(TUIData *tui, int attr_id)
if (italic) {
unibi_out(tui, unibi_enter_italics_mode);
}
+ if (altfont && tui->unibi_ext.enter_altfont_mode != -1) {
+ unibi_out_ext(tui, tui->unibi_ext.enter_altfont_mode);
+ }
if (strikethrough && tui->unibi_ext.enter_strikethrough_mode != -1) {
unibi_out_ext(tui, tui->unibi_ext.enter_strikethrough_mode);
}
@@ -1342,7 +1349,7 @@ static void suspend_event(void **argv)
TUIData *tui = argv[0];
bool enable_mouse = tui->mouse_enabled;
tui_terminal_stop(tui);
- stream_set_blocking(input_global_fd(), true); // normalize stream (#2598)
+ stream_set_blocking(tui->input.in_fd, true); // normalize stream (#2598)
kill(0, SIGTSTP);
@@ -1351,7 +1358,7 @@ static void suspend_event(void **argv)
if (enable_mouse) {
tui_mouse_on(tui);
}
- stream_set_blocking(input_global_fd(), false); // libuv expects this
+ stream_set_blocking(tui->input.in_fd, false); // libuv expects this
}
#endif
@@ -2041,6 +2048,11 @@ static void augment_terminfo(TUIData *tui, const char *term, long vte_version, l
// to the ECMA-48 strikeout/crossed-out attributes.
tui->unibi_ext.enter_strikethrough_mode = unibi_find_ext_str(ut, "smxx");
+ // It should be pretty safe to always enable this, as terminals will ignore
+ // unrecognised SGR numbers.
+ tui->unibi_ext.enter_altfont_mode = (int)unibi_add_ext_str(ut, "ext.enter_altfont_mode",
+ "\x1b[11m");
+
// Dickey ncurses terminfo does not include the setrgbf and setrgbb
// capabilities, proposed by Rüdiger Sonderfeld on 2013-10-15. Adding
// them here when terminfo lacks them is an augmentation, not a fixup.
@@ -2238,12 +2250,12 @@ static void flush_buf(TUIData *tui)
///
/// @see tmux/tty-keys.c fe4e9470bb504357d073320f5d305b22663ee3fd
/// @see https://bugzilla.redhat.com/show_bug.cgi?id=142659
-static const char *tui_get_stty_erase(void)
+static const char *tui_get_stty_erase(int fd)
{
static char stty_erase[2] = { 0 };
#if defined(HAVE_TERMIOS_H)
struct termios t;
- if (tcgetattr(input_global_fd(), &t) != -1) {
+ if (tcgetattr(fd, &t) != -1) {
stty_erase[0] = (char)t.c_cc[VERASE];
stty_erase[1] = '\0';
DLOG("stty/termios:erase=%s", stty_erase);
@@ -2256,9 +2268,10 @@ static const char *tui_get_stty_erase(void)
/// @see TermInput.tk_ti_hook_fn
static const char *tui_tk_ti_getstr(const char *name, const char *value, void *data)
{
+ TermInput *input = data;
static const char *stty_erase = NULL;
if (stty_erase == NULL) {
- stty_erase = tui_get_stty_erase();
+ stty_erase = tui_get_stty_erase(input->in_fd);
}
if (strequal(name, "key_backspace")) {
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index b25fa04c8b..9f1cb87eb0 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -7,8 +7,8 @@
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
+#include <string.h>
-#include "auto/config.h"
#include "klib/kvec.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/ui.h"
@@ -17,8 +17,6 @@
#include "nvim/buffer_defs.h"
#include "nvim/cursor_shape.h"
#include "nvim/drawscreen.h"
-#include "nvim/event/defs.h"
-#include "nvim/event/loop.h"
#include "nvim/ex_getln.h"
#include "nvim/gettext.h"
#include "nvim/globals.h"
@@ -27,15 +25,14 @@
#include "nvim/highlight_defs.h"
#include "nvim/log.h"
#include "nvim/lua/executor.h"
-#include "nvim/main.h"
+#include "nvim/map.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/msgpack_rpc/channel.h"
#include "nvim/option.h"
#include "nvim/os/time.h"
#include "nvim/strings.h"
-#include "nvim/tui/tui.h"
#include "nvim/ui.h"
+#include "nvim/ui_client.h"
#include "nvim/ui_compositor.h"
#include "nvim/vim.h"
#include "nvim/window.h"
diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c
index ff82fd3239..378c0e4831 100644
--- a/src/nvim/ui_client.c
+++ b/src/nvim/ui_client.c
@@ -6,15 +6,18 @@
#include <stdlib.h>
#include "nvim/api/private/helpers.h"
+#include "nvim/channel.h"
#include "nvim/eval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/event/loop.h"
-#include "nvim/event/multiqueue.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
#include "nvim/log.h"
#include "nvim/main.h"
#include "nvim/memory.h"
#include "nvim/msgpack_rpc/channel.h"
+#include "nvim/msgpack_rpc/channel_defs.h"
+#include "nvim/os/os_defs.h"
#include "nvim/tui/tui.h"
#include "nvim/ui.h"
#include "nvim/ui_client.h"
@@ -48,9 +51,16 @@ uint64_t ui_client_start_server(int argc, char **argv)
on_err, CALLBACK_NONE,
false, true, true, false, kChannelStdinPipe,
NULL, 0, 0, NULL, &exit_status);
+
+ // If stdin is not a pty, it is forwarded to the client.
+ // Replace stdin in the TUI process with the tty fd.
if (ui_client_forward_stdin) {
close(0);
- dup(2);
+#ifdef MSWIN
+ os_open_conin_fd();
+#else
+ dup(stderr_isatty ? STDERR_FILENO : STDOUT_FILENO);
+#endif
}
return channel->id;
@@ -74,8 +84,8 @@ void ui_client_run(bool remote_ui)
if (term) {
PUT(opts, "term_name", STRING_OBJ(cstr_to_string(term)));
}
- if (ui_client_bg_respose != kNone) {
- bool is_dark = (ui_client_bg_respose == kTrue);
+ if (ui_client_bg_response != kNone) {
+ bool is_dark = (ui_client_bg_response == kTrue);
PUT_C(opts, "term_background", STRING_OBJ(cstr_as_string(is_dark ? "dark" : "light")));
}
PUT_C(opts, "term_colors", INTEGER_OBJ(t_colors));
diff --git a/src/nvim/ui_client.h b/src/nvim/ui_client.h
index 24b8fad4cc..7e5f847039 100644
--- a/src/nvim/ui_client.h
+++ b/src/nvim/ui_client.h
@@ -1,11 +1,14 @@
#ifndef NVIM_UI_CLIENT_H
#define NVIM_UI_CLIENT_H
+#include <stdbool.h>
#include <stddef.h>
+#include <stdint.h>
#include "nvim/api/private/defs.h"
#include "nvim/grid_defs.h"
#include "nvim/macros.h"
+#include "nvim/types.h"
typedef struct {
const char *name;
@@ -28,17 +31,18 @@ EXTERN bool ui_client_attached INIT(= false);
/// Whether ui client has gotten a response about the bg color of the terminal,
/// kTrue=dark, kFalse=light, kNone=no response yet
-EXTERN TriState ui_client_bg_respose INIT(= kNone);
+EXTERN TriState ui_client_bg_response INIT(= kNone);
/// The ui client should forward its stdin to the nvim process
/// by convention, this uses fd=3 (next free number after stdio)
EXTERN bool ui_client_forward_stdin INIT(= false);
#define UI_CLIENT_STDIN_FD 3
+// uncrustify:off
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ui_client.h.generated.h"
-
# include "ui_events_client.h.generated.h"
#endif
+// uncrustify:on
#endif // NVIM_UI_CLIENT_H
diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c
index ad44e2ca22..9ff9eabff8 100644
--- a/src/nvim/ui_compositor.c
+++ b/src/nvim/ui_compositor.c
@@ -24,7 +24,6 @@
#include "nvim/highlight_group.h"
#include "nvim/log.h"
#include "nvim/macros.h"
-#include "nvim/map.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option_defs.h"
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 85e261fc39..0f12c00f15 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -624,20 +624,20 @@ int u_savecommon(buf_T *buf, linenr_T top, linenr_T bot, linenr_T newbot, int re
// extra fields for uhp
#define UHP_SAVE_NR 1
-static char_u e_not_open[] = N_("E828: Cannot open undo file for writing: %s");
+static char e_not_open[] = N_("E828: Cannot open undo file for writing: %s");
/// Compute the hash for a buffer text into hash[UNDO_HASH_SIZE].
///
/// @param[in] buf The buffer used to compute the hash
/// @param[in] hash Array of size UNDO_HASH_SIZE in which to store the value of
/// the hash
-void u_compute_hash(buf_T *buf, char_u *hash)
+void u_compute_hash(buf_T *buf, uint8_t *hash)
{
context_sha256_T ctx;
sha256_start(&ctx);
for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
char *p = ml_get_buf(buf, lnum, false);
- sha256_update(&ctx, (char_u *)p, (uint32_t)(strlen(p) + 1));
+ sha256_update(&ctx, (uint8_t *)p, strlen(p) + 1);
}
sha256_finish(&ctx, hash);
}
@@ -677,7 +677,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
// Loop over 'undodir'. When reading find the first file that exists.
// When not reading use the first directory that exists or ".".
- char *dirp = (char *)p_udir;
+ char *dirp = p_udir;
while (*dirp != NUL) {
size_t dir_len = copy_option_part(&dirp, dir_name, MAXPATHL, ",");
if (dir_len == 1 && dir_name[0] == '.') {
@@ -765,7 +765,7 @@ static void u_free_uhp(u_header_T *uhp)
/// @param hash The hash of the buffer contents
//
/// @returns false in case of an error.
-static bool serialize_header(bufinfo_T *bi, char_u *hash)
+static bool serialize_header(bufinfo_T *bi, uint8_t *hash)
FUNC_ATTR_NONNULL_ALL
{
buf_T *buf = bi->bi_buf;
@@ -788,7 +788,7 @@ static bool serialize_header(bufinfo_T *bi, char_u *hash)
undo_write_bytes(bi, (uintmax_t)buf->b_ml.ml_line_count, 4);
size_t len = buf->b_u_line_ptr ? strlen(buf->b_u_line_ptr) : 0;
undo_write_bytes(bi, len, 4);
- if (len > 0 && !undo_write(bi, (char_u *)buf->b_u_line_ptr, len)) {
+ if (len > 0 && !undo_write(bi, (uint8_t *)buf->b_u_line_ptr, len)) {
return false;
}
undo_write_bytes(bi, (uintmax_t)buf->b_u_line_lnum, 4);
@@ -1053,7 +1053,7 @@ static bool serialize_uep(bufinfo_T *bi, u_entry_T *uep)
if (!undo_write_bytes(bi, len, 4)) {
return false;
}
- if (len > 0 && !undo_write(bi, (char_u *)uep->ue_array[i], len)) {
+ if (len > 0 && !undo_write(bi, (uint8_t *)uep->ue_array[i], len)) {
return false;
}
}
@@ -1072,18 +1072,18 @@ static u_entry_T *unserialize_uep(bufinfo_T *bi, bool *error, const char *file_n
uep->ue_lcount = undo_read_4c(bi);
uep->ue_size = undo_read_4c(bi);
- char_u **array = NULL;
+ char **array = NULL;
if (uep->ue_size > 0) {
- if ((size_t)uep->ue_size < SIZE_MAX / sizeof(char_u *)) { // -V547
- array = xmalloc(sizeof(char_u *) * (size_t)uep->ue_size);
- memset(array, 0, sizeof(char_u *) * (size_t)uep->ue_size);
+ if ((size_t)uep->ue_size < SIZE_MAX / sizeof(char *)) { // -V547
+ array = xmalloc(sizeof(char *) * (size_t)uep->ue_size);
+ memset(array, 0, sizeof(char *) * (size_t)uep->ue_size);
}
}
- uep->ue_array = (char **)array;
+ uep->ue_array = array;
for (size_t i = 0; i < (size_t)uep->ue_size; i++) {
int line_len = undo_read_4c(bi);
- char_u *line;
+ char *line;
if (line_len >= 0) {
line = undo_read_string(bi, (size_t)line_len);
} else {
@@ -1150,7 +1150,7 @@ static void unserialize_visualinfo(bufinfo_T *bi, visualinfo_T *info)
/// @param[in] buf Buffer for which undo file is written.
/// @param[in] hash Hash value of the buffer text. Must have #UNDO_HASH_SIZE
/// size.
-void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, char_u *const hash)
+void u_write_undo(const char *const name, const bool forceit, buf_T *const buf, uint8_t *const hash)
FUNC_ATTR_NONNULL_ARG(3, 4)
{
char *file_name;
@@ -1209,7 +1209,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
}
goto theend;
} else {
- char_u mbuf[UF_START_MAGIC_LEN];
+ char mbuf[UF_START_MAGIC_LEN];
ssize_t len = read_eintr(fd, mbuf, UF_START_MAGIC_LEN);
close(fd);
if (len < UF_START_MAGIC_LEN
@@ -1342,8 +1342,8 @@ write_error:
#ifdef HAVE_ACL
if (buf->b_ffname != NULL) {
// For systems that support ACL: get the ACL from the original file.
- vim_acl_T acl = os_get_acl((char_u *)buf->b_ffname);
- os_set_acl((char_u *)file_name, acl);
+ vim_acl_T acl = os_get_acl(buf->b_ffname);
+ os_set_acl(file_name, acl);
os_free_acl(acl);
}
#endif
@@ -1359,11 +1359,11 @@ theend:
/// a bit more verbose.
/// Otherwise use curbuf->b_ffname to generate the undo file name.
/// "hash[UNDO_HASH_SIZE]" must be the hash value of the buffer text.
-void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_ATTR_UNUSED)
+void u_read_undo(char *name, const uint8_t *hash, const char *orig_name FUNC_ATTR_UNUSED)
FUNC_ATTR_NONNULL_ARG(2)
{
u_header_T **uhp_table = NULL;
- char_u *line_ptr = NULL;
+ char *line_ptr = NULL;
char *file_name;
if (name == NULL) {
@@ -1377,7 +1377,7 @@ void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_AT
// owner of the text file or equal to the current user.
FileInfo file_info_orig;
FileInfo file_info_undo;
- if (os_fileinfo((const char *)orig_name, &file_info_orig)
+ if (os_fileinfo(orig_name, &file_info_orig)
&& os_fileinfo(file_name, &file_info_undo)
&& file_info_orig.stat.st_uid != file_info_undo.stat.st_uid
&& file_info_undo.stat.st_uid != getuid()) {
@@ -1414,7 +1414,7 @@ void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_AT
};
// Read the undo file header.
- char_u magic_buf[UF_START_MAGIC_LEN];
+ char magic_buf[UF_START_MAGIC_LEN];
if (fread(magic_buf, UF_START_MAGIC_LEN, 1, fp) != 1
|| memcmp(magic_buf, UF_START_MAGIC, UF_START_MAGIC_LEN) != 0) {
semsg(_("E823: Not an undo file: %s"), file_name);
@@ -1426,7 +1426,7 @@ void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_AT
goto error;
}
- char_u read_hash[UNDO_HASH_SIZE];
+ uint8_t read_hash[UNDO_HASH_SIZE];
if (!undo_read(&bi, read_hash, UNDO_HASH_SIZE)) {
corruption_error("hash", file_name);
goto error;
@@ -1608,7 +1608,7 @@ void u_read_undo(char *name, const char_u *hash, const char_u *orig_name FUNC_AT
curbuf->b_u_oldhead = old_idx < 0 ? NULL : uhp_table[old_idx];
curbuf->b_u_newhead = new_idx < 0 ? NULL : uhp_table[new_idx];
curbuf->b_u_curhead = cur_idx < 0 ? NULL : uhp_table[cur_idx];
- curbuf->b_u_line_ptr = (char *)line_ptr;
+ curbuf->b_u_line_ptr = line_ptr;
curbuf->b_u_line_lnum = line_lnum;
curbuf->b_u_line_colnr = line_colnr;
curbuf->b_u_numhead = num_head;
@@ -1743,10 +1743,10 @@ static bool undo_read(bufinfo_T *bi, uint8_t *buffer, size_t size)
/// @param len can be zero to allocate an empty line.
///
/// @returns a pointer to allocated memory or NULL in case of an error.
-static uint8_t *undo_read_string(bufinfo_T *bi, size_t len)
+static char *undo_read_string(bufinfo_T *bi, size_t len)
{
- uint8_t *ptr = xmallocz(len);
- if (len > 0 && !undo_read(bi, ptr, len)) {
+ char *ptr = xmallocz(len);
+ if (len > 0 && !undo_read(bi, (uint8_t *)ptr, len)) {
xfree(ptr);
return NULL;
}
@@ -2238,7 +2238,7 @@ target_zero:
/// @param do_buf_event If `true`, send buffer updates.
static void u_undoredo(int undo, bool do_buf_event)
{
- char_u **newarray = NULL;
+ char **newarray = NULL;
linenr_T newlnum = MAXLNUM;
u_entry_T *nuep;
u_entry_T *newlist = NULL;
@@ -2316,13 +2316,13 @@ static void u_undoredo(int undo, bool do_buf_event)
// delete the lines between top and bot and save them in newarray
if (oldsize > 0) {
- newarray = xmalloc(sizeof(char_u *) * (size_t)oldsize);
+ newarray = xmalloc(sizeof(char *) * (size_t)oldsize);
// delete backwards, it goes faster in most cases
long i;
linenr_T lnum;
for (lnum = bot - 1, i = oldsize; --i >= 0; lnum--) {
// what can we do when we run out of memory?
- newarray[i] = (char_u *)u_save_line(lnum);
+ newarray[i] = u_save_line(lnum);
// remember we deleted the last line in the buffer, and a
// dummy empty line will be inserted
if (curbuf->b_ml.ml_line_count == 1) {
@@ -2348,7 +2348,7 @@ static void u_undoredo(int undo, bool do_buf_event)
}
xfree(uep->ue_array[i]);
}
- xfree((char_u *)uep->ue_array);
+ xfree(uep->ue_array);
}
// Adjust marks
@@ -2378,7 +2378,7 @@ static void u_undoredo(int undo, bool do_buf_event)
u_newcount += newsize;
u_oldcount += oldsize;
uep->ue_size = oldsize;
- uep->ue_array = (char **)newarray;
+ uep->ue_array = newarray;
uep->ue_bot = top + newsize + 1;
// insert this entry in front of the new entry list
@@ -2565,11 +2565,11 @@ static void u_undo_end(bool did_undo, bool absolute, bool quiet)
uhp = curbuf->b_u_newhead;
}
- char_u msgbuf[80];
+ char msgbuf[80];
if (uhp == NULL) {
*msgbuf = NUL;
} else {
- undo_fmt_time((char *)msgbuf, sizeof(msgbuf), uhp->uh_time);
+ undo_fmt_time(msgbuf, sizeof(msgbuf), uhp->uh_time);
}
{
@@ -2935,7 +2935,7 @@ static void u_freeentries(buf_T *buf, u_header_T *uhp, u_header_T **uhpp)
#ifdef U_DEBUG
uhp->uh_magic = 0;
#endif
- xfree((char_u *)uhp);
+ xfree(uhp);
buf->b_u_numhead--;
}
@@ -2945,11 +2945,11 @@ static void u_freeentry(u_entry_T *uep, long n)
while (n > 0) {
xfree(uep->ue_array[--n]);
}
- xfree((char_u *)uep->ue_array);
+ xfree(uep->ue_array);
#ifdef U_DEBUG
uep->ue_magic = 0;
#endif
- xfree((char_u *)uep);
+ xfree(uep);
}
/// invalidate the undo buffer; called when storage has already been released
@@ -2985,10 +2985,12 @@ void u_saveline(linenr_T lnum)
/// (this is used externally for crossing a line while in insert mode)
void u_clearline(void)
{
- if (curbuf->b_u_line_ptr != NULL) {
- XFREE_CLEAR(curbuf->b_u_line_ptr);
- curbuf->b_u_line_lnum = 0;
+ if (curbuf->b_u_line_ptr == NULL) {
+ return;
}
+
+ XFREE_CLEAR(curbuf->b_u_line_ptr);
+ curbuf->b_u_line_lnum = 0;
}
/// Implementation of the "U" command.
diff --git a/src/nvim/usercmd.c b/src/nvim/usercmd.c
index 883d7321d2..ef13f67e49 100644
--- a/src/nvim/usercmd.c
+++ b/src/nvim/usercmd.c
@@ -89,12 +89,15 @@ static const char *command_complete[] = {
[EXPAND_SYNTIME] = "syntime",
[EXPAND_SETTINGS] = "option",
[EXPAND_PACKADD] = "packadd",
+ [EXPAND_RUNTIME] = "runtime",
[EXPAND_SHELLCMD] = "shellcmd",
[EXPAND_SIGN] = "sign",
[EXPAND_TAGS] = "tag",
[EXPAND_TAGS_LISTFILES] = "tag_listfiles",
[EXPAND_USER] = "user",
[EXPAND_USER_VARS] = "var",
+ [EXPAND_BREAKPOINT] = "breakpoint",
+ [EXPAND_SCRIPTNAMES] = "scriptnames",
};
/// List of names of address types. Must be alphabetical for completion.
@@ -1422,7 +1425,7 @@ static size_t uc_check_code(char *code, size_t len, char *buf, ucmd_T *cmd, exar
ct_NONE,
} type = ct_NONE;
- if ((vim_strchr("qQfF", *p) != NULL) && p[1] == '-') {
+ if ((vim_strchr("qQfF", (uint8_t)(*p)) != NULL) && p[1] == '-') {
quote = (*p == 'q' || *p == 'Q') ? 1 : 2;
p += 2;
l -= 2;
@@ -1430,7 +1433,7 @@ static size_t uc_check_code(char *code, size_t len, char *buf, ucmd_T *cmd, exar
l++;
if (l <= 1) {
- type = ct_NONE;
+ // type = ct_NONE;
} else if (STRNICMP(p, "args>", l) == 0) {
type = ct_ARGS;
} else if (STRNICMP(p, "bang>", l) == 0) {
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 92122b2523..3324ac2a94 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -29,6 +29,7 @@
#include "nvim/highlight_defs.h"
#include "nvim/lua/executor.h"
#include "nvim/mbyte.h"
+#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option_defs.h"
#include "nvim/os/os_defs.h"
@@ -63,12 +64,6 @@ static char *features[] = {
"-acl",
#endif
-#if defined(HAVE_ICONV)
- "+iconv",
-#else
- "-iconv",
-#endif
-
"+tui",
NULL
};
@@ -800,7 +795,7 @@ static const int included_patches[] = {
1702,
1701,
// 1700,
- // 1699,
+ 1699,
1698,
1697,
1696,
@@ -1366,7 +1361,7 @@ static const int included_patches[] = {
// 1136,
1135,
1134,
- // 1133,
+ 1133,
1132,
1131,
1130,
@@ -1679,7 +1674,7 @@ static const int included_patches[] = {
823,
822,
821,
- // 820,
+ 820,
819,
818,
817,
@@ -2790,24 +2785,18 @@ void maybe_intro_message(void)
/// @param colon true for ":intro"
void intro_message(int colon)
{
- int i;
- long row;
- long blanklines;
- int sponsor;
- char *p;
static char *(lines[]) = {
N_(NVIM_VERSION_LONG),
"",
N_("Nvim is open source and freely distributable"),
- N_("https://neovim.io/#chat"),
+ "https://neovim.io/#chat",
"",
N_("type :help nvim<Enter> if you are new! "),
N_("type :checkhealth<Enter> to optimize Nvim"),
N_("type :q<Enter> to exit "),
N_("type :help<Enter> for help "),
"",
- N_("type :help news<Enter> to see changes in")
- " v" STR(NVIM_VERSION_MAJOR) "." STR(NVIM_VERSION_MINOR),
+ N_("type :help news<Enter> to see changes in v%s.%s"),
"",
N_("Help poor children in Uganda!"),
N_("type :help iccf<Enter> for information "),
@@ -2817,7 +2806,7 @@ void intro_message(int colon)
size_t lines_size = ARRAY_SIZE(lines);
assert(lines_size <= LONG_MAX);
- blanklines = Rows - ((long)lines_size - 1L);
+ long blanklines = Rows - ((long)lines_size - 1L);
// Don't overwrite a statusline. Depends on 'cmdheight'.
if (p_ls > 1) {
@@ -2830,17 +2819,27 @@ void intro_message(int colon)
// Show the sponsor and register message one out of four times, the Uganda
// message two out of four times.
- sponsor = (int)time(NULL);
+ int sponsor = (int)time(NULL);
sponsor = ((sponsor & 2) == 0) - ((sponsor & 4) == 0);
// start displaying the message lines after half of the blank lines
- row = blanklines / 2;
+ long row = blanklines / 2;
if (((row >= 2) && (Columns >= 50)) || colon) {
- for (i = 0; i < (int)ARRAY_SIZE(lines); i++) {
- p = lines[i];
+ for (int i = 0; i < (int)ARRAY_SIZE(lines); i++) {
+ char *p = lines[i];
+ char *mesg = NULL;
+ int mesg_size = 0;
- if (sponsor != 0) {
+ if (strstr(p, "news") != NULL) {
+ p = _(p);
+ mesg_size = snprintf(NULL, 0, p,
+ STR(NVIM_VERSION_MAJOR), STR(NVIM_VERSION_MINOR));
+ assert(mesg_size > 0);
+ mesg = xmallocz((size_t)mesg_size);
+ snprintf(mesg, (size_t)mesg_size + 1, p,
+ STR(NVIM_VERSION_MAJOR), STR(NVIM_VERSION_MINOR));
+ } else if (sponsor != 0) {
if (strstr(p, "children") != NULL) {
p = sponsor < 0
? N_("Sponsor Vim development!")
@@ -2849,15 +2848,25 @@ void intro_message(int colon)
p = sponsor < 0
? N_("type :help sponsor<Enter> for information ")
: N_("type :help register<Enter> for information ");
- } else if (strstr(p, "Orphans") != NULL) {
- p = N_("menu Help->Sponsor/Register for information ");
}
}
- if (*p != NUL) {
- do_intro_line(row, _(p), 0);
+ if (mesg == NULL) {
+ if (*p != NUL) {
+ mesg = _(p);
+ } else {
+ mesg = "";
+ }
+ }
+
+ if (*mesg != NUL) {
+ do_intro_line(row, mesg, 0);
}
row++;
+
+ if (mesg_size > 0) {
+ XFREE_CLEAR(mesg);
+ }
}
}
diff --git a/src/nvim/vim.h b/src/nvim/vim.h
index c395eb438c..3c765f8eb2 100644
--- a/src/nvim/vim.h
+++ b/src/nvim/vim.h
@@ -154,6 +154,9 @@ enum {
EXPAND_MAPCLEAR,
EXPAND_ARGLIST,
EXPAND_DIFF_BUFFERS,
+ EXPAND_BREAKPOINT,
+ EXPAND_SCRIPTNAMES,
+ EXPAND_RUNTIME,
EXPAND_CHECKHEALTH,
EXPAND_LUA,
};
diff --git a/src/nvim/viml/parser/expressions.c b/src/nvim/viml/parser/expressions.c
index 0b19526fa0..53224f2ee9 100644
--- a/src/nvim/viml/parser/expressions.c
+++ b/src/nvim/viml/parser/expressions.c
@@ -1826,7 +1826,7 @@ static void parse_quoted_string(ParserState *const pstate, ExprASTNode *const no
flags |= FSK_SIMPLIFY;
}
const size_t special_len = trans_special(&p, (size_t)(e - p),
- (char_u *)v_p, flags, false, NULL);
+ v_p, flags, false, NULL);
if (special_len != 0) {
v_p += special_len;
} else {
@@ -2497,7 +2497,6 @@ viml_pexpr_parse_bracket_closing_error:
NEW_NODE_WITH_CUR_POS(cur_node, kExprNodeListLiteral);
*top_node_p = cur_node;
kvi_push(ast_stack, &cur_node->children);
- want_node = kENodeValue;
if (cur_pt == kEPTAssignment) {
// Additional assignment parse type allows to easily forbid nested
// lists.
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 2bcbef14b0..6b40ccdb84 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -11,12 +11,14 @@
#include <stdlib.h>
#include <string.h>
+#include "klib/kvec.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/arglist.h"
#include "nvim/ascii.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
#include "nvim/decoration.h"
@@ -59,6 +61,7 @@
#include "nvim/option.h"
#include "nvim/optionstr.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/path.h"
#include "nvim/plines.h"
#include "nvim/pos.h"
@@ -505,7 +508,7 @@ wingotofile:
CHECK_CMDWIN;
linenr_T lnum = -1;
- char *ptr = (char *)grab_file_name(Prenum1, &lnum);
+ char *ptr = grab_file_name(Prenum1, &lnum);
if (ptr != NULL) {
tabpage_T *oldtab = curtab;
win_T *oldwin = curwin;
@@ -753,20 +756,20 @@ void win_set_minimal_style(win_T *wp)
// Hide EOB region: use " " fillchar and cleared highlighting
if (wp->w_p_fcs_chars.eob != ' ') {
- char_u *old = (char_u *)wp->w_p_fcs;
+ char *old = wp->w_p_fcs;
wp->w_p_fcs = ((*old == NUL)
? xstrdup("eob: ")
- : concat_str((char *)old, ",eob: "));
- free_string_option((char *)old);
+ : concat_str(old, ",eob: "));
+ free_string_option(old);
}
// TODO(bfredl): this could use a highlight namespace directly,
// and avoid peculiarities around window options
- char_u *old = (char_u *)wp->w_p_winhl;
+ char *old = wp->w_p_winhl;
wp->w_p_winhl = ((*old == NUL)
? xstrdup("EndOfBuffer:")
- : concat_str((char *)old, ",EndOfBuffer:"));
- free_string_option((char *)old);
+ : concat_str(old, ",EndOfBuffer:"));
+ free_string_option(old);
parse_winhl_opt(wp);
// signcolumn: use 'auto'
@@ -2524,24 +2527,23 @@ void close_windows(buf_T *buf, bool keep_curwin)
RedrawingDisabled--;
}
-/// Check that the specified window is the last one.
-/// @param win counted even if floating
-///
-/// @return true if the specified window is the only window that exists,
-/// false if there is another, possibly in another tab page.
+/// Check if "win" is the last non-floating window that exists.
bool last_window(win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
return one_window(win) && first_tabpage->tp_next == NULL;
}
-/// Check if current tab page contains no more than one window other than `aucmd_win[]`.
-/// @param counted_float counted even if floating, but not if it is `aucmd_win[]`
-bool one_window(win_T *counted_float) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+/// Check if "win" is the only non-floating window in the current tabpage.
+bool one_window(win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
+ if (win->w_floating) {
+ return false;
+ }
+
bool seen_one = false;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (!is_aucmd_win(wp) && (!wp->w_floating || wp == counted_float)) {
+ if (!wp->w_floating) {
if (seen_one) {
return false;
}
@@ -2597,6 +2599,7 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev
if (!ONE_WINDOW) {
return false;
}
+
buf_T *old_curbuf = curbuf;
Terminal *term = win->w_buffer ? win->w_buffer->terminal : NULL;
@@ -2614,8 +2617,8 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev
goto_tabpage_tp(alt_tabpage(), false, true);
// save index for tabclosed event
- char_u prev_idx[NUMBUFLEN];
- snprintf((char *)prev_idx, NUMBUFLEN, "%i", tabpage_index(prev_curtab));
+ char prev_idx[NUMBUFLEN];
+ snprintf(prev_idx, NUMBUFLEN, "%i", tabpage_index(prev_curtab));
// Safety check: Autocommands may have closed the window when jumping
// to the other tab page.
@@ -4061,7 +4064,7 @@ void free_tabpage(tabpage_T *tp)
/// tabpage in case of 0.
/// @param filename Will be passed to apply_autocmds().
/// @return Was the new tabpage created successfully? FAIL or OK.
-int win_new_tabpage(int after, char_u *filename)
+int win_new_tabpage(int after, char *filename)
{
tabpage_T *old_curtab = curtab;
@@ -4124,7 +4127,7 @@ int win_new_tabpage(int after, char_u *filename)
apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf);
apply_autocmds(EVENT_WINENTER, NULL, NULL, false, curbuf);
- apply_autocmds(EVENT_TABNEW, (char *)filename, (char *)filename, false, curbuf);
+ apply_autocmds(EVENT_TABNEW, filename, filename, false, curbuf);
apply_autocmds(EVENT_TABENTER, NULL, NULL, false, curbuf);
return OK;
@@ -4142,12 +4145,13 @@ int may_open_tabpage(void)
{
int n = (cmdmod.cmod_tab == 0) ? postponed_split_tab : cmdmod.cmod_tab;
- if (n != 0) {
- cmdmod.cmod_tab = 0; // reset it to avoid doing it twice
- postponed_split_tab = 0;
- return win_new_tabpage(n, NULL);
+ if (n == 0) {
+ return FAIL;
}
- return FAIL;
+
+ cmdmod.cmod_tab = 0; // reset it to avoid doing it twice
+ postponed_split_tab = 0;
+ return win_new_tabpage(n, NULL);
}
// Create up to "maxcount" tabpages with empty windows.
@@ -4492,11 +4496,12 @@ void goto_tabpage_tp(tabpage_T *tp, bool trigger_enter_autocmds, bool trigger_le
/// @return true if the tab page is valid, false otherwise.
bool goto_tabpage_lastused(void)
{
- if (valid_tabpage(lastused_tabpage)) {
- goto_tabpage_tp(lastused_tabpage, true, true);
- return true;
+ if (!valid_tabpage(lastused_tabpage)) {
+ return false;
}
- return false;
+
+ goto_tabpage_tp(lastused_tabpage, true, true);
+ return true;
}
// Enter window "wp" in tab page "tp".
@@ -6754,7 +6759,7 @@ static void frame_add_height(frame_T *frp, int n)
// Get the file name at the cursor.
// If Visual mode is active, use the selected text if it's in one line.
// Returns the name in allocated memory, NULL for failure.
-char_u *grab_file_name(long count, linenr_T *file_lnum)
+char *grab_file_name(long count, linenr_T *file_lnum)
{
int options = FNAME_MESS | FNAME_EXP | FNAME_REL | FNAME_UNESC;
if (VIsual_active) {
@@ -6764,12 +6769,12 @@ char_u *grab_file_name(long count, linenr_T *file_lnum)
return NULL;
}
// Only recognize ":123" here
- if (file_lnum != NULL && ptr[len] == ':' && isdigit(ptr[len + 1])) {
+ if (file_lnum != NULL && ptr[len] == ':' && isdigit((uint8_t)ptr[len + 1])) {
char *p = ptr + len + 1;
*file_lnum = (linenr_T)getdigits_long(&p, false, 0);
}
- return (char_u *)find_file_name_in_path(ptr, len, options, count, curbuf->b_ffname);
+ return find_file_name_in_path(ptr, len, options, count, curbuf->b_ffname);
}
return file_name_at_cursor(options | FNAME_HYP, count, file_lnum);
}
@@ -6785,10 +6790,10 @@ char_u *grab_file_name(long count, linenr_T *file_lnum)
// FNAME_EXP expand to path
// FNAME_HYP check for hypertext link
// FNAME_INCL apply "includeexpr"
-char_u *file_name_at_cursor(int options, long count, linenr_T *file_lnum)
+char *file_name_at_cursor(int options, long count, linenr_T *file_lnum)
{
- return file_name_in_line((char_u *)get_cursor_line_ptr(),
- curwin->w_cursor.col, options, count, (char_u *)curbuf->b_ffname,
+ return file_name_in_line(get_cursor_line_ptr(),
+ curwin->w_cursor.col, options, count, curbuf->b_ffname,
file_lnum);
}
@@ -6796,11 +6801,11 @@ char_u *file_name_at_cursor(int options, long count, linenr_T *file_lnum)
/// @param file_lnum line number after the file name
///
/// @return the name of the file under or after ptr[col]. Otherwise like file_name_at_cursor().
-char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u *rel_fname,
- linenr_T *file_lnum)
+char *file_name_in_line(char *line, int col, int options, long count, char *rel_fname,
+ linenr_T *file_lnum)
{
// search forward for what could be the start of a file name
- char *ptr = (char *)line + col;
+ char *ptr = line + col;
while (*ptr != NUL && !vim_isfilec((uint8_t)(*ptr))) {
MB_PTR_ADV(ptr);
}
@@ -6817,8 +6822,8 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u
// Search backward for first char of the file name.
// Go one char back to ":" before "//" even when ':' is not in 'isfname'.
- while ((char_u *)ptr > line) {
- if ((len = (size_t)(utf_head_off((char *)line, ptr - 1))) > 0) {
+ while (ptr > line) {
+ if ((len = (size_t)(utf_head_off(line, ptr - 1))) > 0) {
ptr -= len + 1;
} else if (vim_isfilec((uint8_t)ptr[-1])
|| ((options & FNAME_HYP) && path_is_url(ptr - 1))) {
@@ -6833,7 +6838,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u
len = 0;
while (vim_isfilec((uint8_t)ptr[len]) || (ptr[len] == '\\' && ptr[len + 1] == ' ')
|| ((options & FNAME_HYP) && path_is_url(ptr + len))
- || (is_url && vim_strchr(":?&=", ptr[len]) != NULL)) {
+ || (is_url && vim_strchr(":?&=", (uint8_t)ptr[len]) != NULL)) {
// After type:// we also include :, ?, & and = as valid characters, so that
// http://google.com:8080?q=this&that=ok works.
if ((ptr[len] >= 'A' && ptr[len] <= 'Z')
@@ -6854,7 +6859,7 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u
// If there is trailing punctuation, remove it.
// But don't remove "..", could be a directory name.
- if (len > 2 && vim_strchr(".,:;!", ptr[len - 1]) != NULL
+ if (len > 2 && vim_strchr(".,:;!", (uint8_t)ptr[len - 1]) != NULL
&& ptr[len - 2] != '.') {
len--;
}
@@ -6875,17 +6880,17 @@ char_u *file_name_in_line(char_u *line, int col, int options, long count, char_u
p = skipwhite(p);
}
if (*p != NUL) {
- if (!isdigit(*p)) {
+ if (!isdigit((uint8_t)(*p))) {
p++; // skip the separator
}
p = skipwhite(p);
- if (isdigit(*p)) {
+ if (isdigit((uint8_t)(*p))) {
*file_lnum = (linenr_T)getdigits_long(&p, false, 0);
}
}
}
- return (char_u *)find_file_name_in_path(ptr, len, options, count, (char *)rel_fname);
+ return find_file_name_in_path(ptr, len, options, count, rel_fname);
}
/// Add or remove a status line from window(s), according to the
@@ -7248,11 +7253,12 @@ static void clear_snapshot(tabpage_T *tp, int idx)
static void clear_snapshot_rec(frame_T *fr)
{
- if (fr != NULL) {
- clear_snapshot_rec(fr->fr_next);
- clear_snapshot_rec(fr->fr_child);
- xfree(fr);
+ if (fr == NULL) {
+ return;
}
+ clear_snapshot_rec(fr->fr_next);
+ clear_snapshot_rec(fr->fr_child);
+ xfree(fr);
}
/// Traverse a snapshot to find the previous curwin.
diff --git a/src/nvim/window.h b/src/nvim/window.h
index f348f102c9..4ab2bea60a 100644
--- a/src/nvim/window.h
+++ b/src/nvim/window.h
@@ -6,6 +6,7 @@
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
+#include "nvim/macros.h"
#include "nvim/mark.h"
#include "nvim/os/os.h"
#include "nvim/os/os_defs.h"